Load data for young and old neural stem cells sequenced with the Smart-Seq2 protocol

NSCs_annotation <- read.csv(file = "count_table/NSCs_annotation.csv" , row.names = 1)
TPM_NSCs <- read.csv(file = "count_table/TPM_NSCs.csv" , row.names = 1)

Make the cell names also rownames

rownames(NSCs_annotation) <- NSCs_annotation$cell
head( NSCs_annotation )

Load the R packages needed for the analysis

We need the Matrix package to use sparse matrices to save memory while computing. The ggplot2 package is used for plotting. Seurat is used to create PCA and tSNE plots.

require(Matrix)
Loading required package: Matrix
require(tidyverse)
Loading required package: tidyverse
── Attaching packages ────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 2.2.1     ✔ purrr   0.2.4
✔ tibble  1.4.2     ✔ dplyr   0.7.4
✔ tidyr   0.7.2     ✔ stringr 1.3.1
✔ readr   1.1.1     ✔ forcats 0.3.0
── Conflicts ───────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::expand() masks Matrix::expand()
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
require(ggplot2)
require(gridExtra)
Loading required package: gridExtra

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine
require(tidyverse)
require(clusterProfiler)
Loading required package: clusterProfiler
Loading required package: DOSE
DOSE v3.4.0  For help: https://guangchuangyu.github.io/DOSE

If you use DOSE in published research, please cite:
Guangchuang Yu, Li-Gen Wang, Guang-Rong Yan, Qing-Yu He. DOSE: an R/Bioconductor package for Disease Ontology Semantic and Enrichment analysis. Bioinformatics 2015, 31(4):608-609

clusterProfiler v3.4.4  For help: https://guangchuangyu.github.io/clusterProfiler

If you use clusterProfiler in published research, please cite:
Guangchuang Yu., Li-Gen Wang, Yanyan Han, Qing-Yu He. clusterProfiler: an R package for comparing biological themes among gene clusters. OMICS: A Journal of Integrative Biology. 2012, 16(5):284-287.

Attaching package: ‘clusterProfiler’

The following object is masked from ‘package:purrr’:

    simplify
require(Seurat)
Loading required package: Seurat
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:ggplot2’:

    ggsave
set.seed(123)

Load the monocle pseudotime results

pseudotime_ordering <- read.csv(file = "Monocle/pseudotime_ordering.csv" , row.names = 1 )

Check innate immune response and interferon response GO category genes

Create a Seurat object using the TPM values for the SmartSeq2 data and use the same normalization strategy as for the 10X sequencing run.

Use the TPM data.frame to initialize a Seurat object

TPM_NSC <- remove_rownames(TPM_NSCs) %>% column_to_rownames( var = "ensembl_gene_id")
seurat_sms2 <- CreateSeuratObject(raw.data = TPM_NSC  , min.cells = 3, project = "young_vs_old_SmartSeq2")

Set identity to NSC to begin with.

seurat_sms2 <- SetIdent(object = seurat_sms2 , ident.use = "NSC")
VlnPlot(object = seurat_sms2, features.plot = c("nGene", "nUMI"))

Add metadata: age of the animal, cell name and celltype (activation state)

seurat_sms2 <- AddMetaData(object = seurat_sms2, metadata = NSCs_annotation )

Log-normalize the TPM data

seurat_sms2 <- NormalizeData(object = seurat_sms2, normalization.method = "LogNormalize")
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
seurat_sms2 <- ScaleData(object = seurat_sms2, vars.to.regress = c("nUMI", "nGene"))

Regress out difference between S phase and G2/M Phase

First we load the genes related to the cell cycle phases G2/M and S and make them matching to the gene symbols in the dataset by converting to ENSEMBL_IDs .

s.genes <- bitr(geneID = stringr::str_to_title(cc.genes$s.genes) , fromType = "SYMBOL" , toType = "ENSEMBL" ,drop = FALSE ,OrgDb = "org.Mm.eg.db")
Loading required package: org.Mm.eg.db
Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: IRanges
Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:dplyr’:

    first, rename

The following object is masked from ‘package:tidyr’:

    expand

The following object is masked from ‘package:Matrix’:

    expand

The following object is masked from ‘package:base’:

    expand.grid


Attaching package: ‘IRanges’

The following objects are masked from ‘package:dplyr’:

    collapse, desc, slice

The following object is masked from ‘package:purrr’:

    reduce


Attaching package: ‘AnnotationDbi’

The following object is masked from ‘package:dplyr’:

    select


'select()' returned 1:1 mapping between keys and columns
2.33% of input gene IDs are fail to map...
g2m.genes <- bitr(geneID = stringr::str_to_title(cc.genes$g2m.genes) , fromType = "SYMBOL" , toType = "ENSEMBL" ,drop = FALSE ,OrgDb = "org.Mm.eg.db")
'select()' returned 1:many mapping between keys and columns
3.7% of input gene IDs are fail to map...
seurat_sms2 <- CellCycleScoring(object = seurat_sms2, s.genes = s.genes$ENSEMBL , g2m.genes = g2m.genes$ENSEMBL , set.ident = FALSE)

Then we calculate the difference between the cell cycle scores and regress our data on that difference.

seurat_sms2@meta.data$CC.Difference <- seurat_sms2@meta.data$S.Score - seurat_sms2@meta.data$G2M.Score
seurat_sms2 <- ScaleData(object = seurat_sms2, vars.to.regress = "CC.Difference", display.progress = FALSE)

Load a list of genes from the innate immune response GO category

results_interferon_response_immune <- structure(list(mgi_symbol = c("Uba7", "Ube2l6", "Ube2e1", "Ube2e2", 
"Isg15", "Ikbke", "Setd2", "A230050P20Rik", "Mx2", "Shmt2", "Irgm2", 
"Dnaja3", "Kynu", "Bst2", "Sec61a1", "Cited1", "H2-Aa", "Slc11a1", 
"Gch1", "Ubd", "Il23r", "Slc30a8", "Cxcl16", "Cyp27b1", "Trim21", 
"Ifitm2", "Ifitm1", "Ifitm3", "Adamts13", "Tgtp2", "Tgtp1", "Snca", 
"Cd40", "Mefv", "Ciita", "Klhl20", "Adar", "Ifnar2", "Eif2ak2", 
"Plscr1", "Lamp3", "Xaf1", "Stat1", "S100a8", "Trdc", "S100a9", 
"Aim2", "Mb21d1", "Irf1", "Pglyrp4", "Sdhaf4", "Ddx3x", "Defb1", 
"Serinc5", "Ddx58", "Defb12", "Defb34", "Nlrp10", "Rela", "Gata3", 
"Csf1r", "Igha", "Defb15", "Rnase6", "Defb35", "Defb13", "Pglyrp3", 
"Ighg2c", "Krt16", "Tril", "Nlrp9c", "Bpifb3", "Pik3ca", "Nlrp1a", 
"Nlrp9b", "Ighg3", "Ighd", "Ighm", "Nlrp1b", "Cfi", "Ly96", "Jchain", 
"C8b", "Nlrx1", "Cybb", "Pml", "C8a", "Tnk1", "Polr3c", "Il1rap", 
"Rbm14", "Polr3e", "Anxa1", "Cfd", "Ifnk", "Fcnb", "Nr1h4", "Defb43", 
"Nono", "5730559C18Rik", "Hmgb3", "Defb30", "Sh2d1b2", "Ighv5-2", 
"Ighv2-2", "Tnfaip8l2", "Tarm1", "Ighv5-4", "Bpifa1", "Nod2", 
"Ighv2-3", "Otulin", "Ighv5-6", "Bpifb1", "Ifi202b", "Ighv5-9", 
"Fcgr1", "Trim28", "Arg1", "Trbc1", "Pik3cg", "Defb18", "Defb41", 
"Ighv2-5", "Ighv5-12", "Ighv2-6", "Ighv5-9-1", "Polr3g", "Cyld", 
"Sh2d1a", "Zap70", "Ifit3", "Rsad2", "Msrb1", "Ifit1", "Cr1l", 
"Cfp", "Sp110", "Trbc2", "Casp4", "Nod1", "Sla2", "Smpdl3b", 
"Tlr5", "Ighv5-12-4", "Ighv2-9-1", "Axl", "Map3k5", "Cd55", "Blk", 
"Myd88", "Tnfsf4", "Ighv2-6-8", "Ighv2-7", "Ighv5-15", "Ighv5-16", 
"Ighv5-17", "Ighv2-9", "Irf5", "Ighv7-1", "Ighv7-2", "Ighv14-1", 
"Ighv4-1", "Ighv3-1", "Ighv11-1", "Trim11", "Sla", "Ighv14-2", 
"Ighv11-2", "Ighv14-3", "Trim14", "Ighv16-1", "Ighv9-1", "Dhx58", 
"Trim13", "Pqbp1", "Cyba", "Ighv9-2", "Ighv9-3", "Ighv7-3", "Ankhd1", 
"Ighv14-4", "Ighv3-3", "Oasl2", "Ighv7-4", "Ighv3-4", "Nrros", 
"Tlr13", "Fes", "Ticam1", "Ighv3-6", "Ighv9-4", "Apobec3", "Ighv3-8", 
"Ighv13-2", "Ankrd17", "Trim15", "Ighv12-3", "Ighv6-3", "Oasl1", 
"Trim10", "Tlr1", "Ighv6-4", "C4bp", "Trim5", "Tlr6", "Trim31", 
"Polr3b", "Mavs", "Vnn1", "Apcs", "Akirin2", "Ssc5d", "Trim12a", 
"Polr3d", "Clec5a", "Fgg", "Dab2ip", "Hmgb2", "Fga", "Fgb", "Trim12c", 
"Fgr", "Ipo7", "Mst1r", "Trim30b", "Trim30c", "Sfpq", "Il34", 
"Trim25", "Trim30a", "Trim30d", "Pspc1", "Card9", "Mbl1", "Ptk2", 
"Lcn2", "Abl1", "Sftpd", "Tlr8", "Pycard", "Ighv6-5", "Tlr2", 
"Ighv6-6", "Ighv6-7", "Serping1", "Tlr7", "Src", "Ighv8-2", "Iglc1", 
"Ighv10-1", "Ighv1-4", "Il1f6", "Iglc4", "Ighv1-5", "Ighv10-3", 
"Ighv1-7", "Iglc2", "Defb23", "Gper1", "Cnpy3", "Trdv4", "Defb20", 
"Defb22", "Defb26", "Defb28", "Il1f5", "Defb29", "Ighv15-2", 
"Ighv1-9", "Defb21", "Itch", "Pglyrp1", "Nfkb1", "Defb19", "Defb45", 
"Il1rl2", "Defb36", "Mid2", "Defb25", "Ighv1-11", "Ighv1-12", 
"Ighv1-15", "Ighv1-16", "Grb2", "Ighv1-18", "Ighv1-19", "Ighv1-20", 
"Map4k2", "Il1f8", "Pik3cb", "Adam15", "Ighv1-22", "Bcl10", "Ighv1-23", 
"Ighv1-24", "Ighv1-26", "Prkdc", "Irak4", "F2rl1", "Adgrb1", 
"Isg20", "C1qb", "C1qc", "C1qa", "Mr1", "Polr3a", "Tlr9", "Ighv1-76", 
"Optn", "Ighv1-77", "Ptx3", "Ighv1-78", "Zbtb1", "Grap", "Lbp", 
"Arhgef2", "Mcoln2", "Ighv1-80", "Tbk1", "Ighv1-81", "Ifih1", 
"Ighv1-31", "Bmx", "Ighv1-82", "Ighv1-34", "Ly86", "Nlrc5", "Ighv1-85", 
"Polr3f", "Ighv1-36", "Ighv1-37", "Tlr11", "Trim27", "Malt1", 
"Fadd", "Ighv1-39", "Ighv1-42", "Ighv1-43", "Btk", "Dcst1", "Parp14", 
"Ighv1-47", "Ighv8-4", "Ighv1-49", "Itk", "Ighv8-5", "Ighv1-50", 
"Trim26", "Chid1", "Csk", "Fcer1g", "Ighv1-52", "Ighv1-53", "Ighv8-6", 
"Naip2", "Nlrp3", "C8g", "Ighv1-54", "Csf1", "Traf3", "Ighv1-55", 
"Ighv1-56", "Elf4", "Dtx3l", "Irak1", "Naip6", "Parp9", "Ighv8-8", 
"Ighv1-58", "Pik3cd", "Hck", "Ighv1-59", "Cd180", "Irf3", "Ighv1-61", 
"Ighv1-62-1", "Ifnl2", "Relb", "Ifnl3", "Fyn", "Ighv1-62-2", 
"Ighv1-62-3", "Hmgb1", "Tlr12", "Ighv8-9", "Yes1", "Ighv1-63", 
"Ighv1-64", "Tbkbp1", "Siglecg", "Ighv8-11", "Ighv1-66", "Cfh", 
"Zc3hav1", "Ighv1-67", "Ighv1-69", "Ighv8-12", "Havcr2", "4933415F23Rik", 
"Trim32", "Ighv8-13", "C3", "Ighv1-74", "Trim62", "Hexim1", "Matr3", 
"Ighv1-75", "Slpi", "Zfp809", "Igll1", "Arid5a", "Tollip", "Tlr4", 
"Syk", "C4b", "Cd244", "Fbxo9", "Ly9", "Ifnb1", "Zfp683", "Ifna15", 
"Ifna9", "Ifna14", "Ifna12", "Lck", "Serinc3", "Nlrp6", "Camp", 
"Ifna13", "Ifna16", "Ifnab", "Lyn", "Gm13271", "Gm13283", "Gm13290", 
"Gm13289", "Gm13272", "Cd24a", "Spon2", "Lgr4", "Ifnz", "Gm13276", 
"Gm13277", "Gm13278", "Tlr3", "Gm13275", "Gm13279", "Gm13285", 
"Gm13287", "Gm13288", "Ifna11", "Ifna4", "Oas2", "Prkd1", "Oas3", 
"Slamf1", "Marco", "Ifne", "Rarres2", "Clec4a2", "Treml4", "Oas1a", 
"Slamf6", "Fcna", "Sarm1", "Atg5", "Trim59", "Clec4n", "Herc6", 
"Ripk2", "Irgm1", "Prdm1", "Hc", "Clec4d", "Clec4e", "Ticam2", 
"Trem2", "Il27", "Frk", "Mif", "Ptk2b", "C1rl", "Irf7", "C1ra", 
"C1rb", "C1s2", "Polr3k", "Zbp1", "Trim35", "Il23a", "C2", "Cfb", 
"Padi4", "Cactin", "Masp2", "Klrg1", "Arg2", "Ptk6", "Clec7a", 
"Rnf135", "Txk", "Klrk1", "Sec14l1", "Crcp", "Styk1", "Tmem173", 
"Atg12", "Gm17416", "Iigp1", "Polr3h", "Riok3", "Cd14", "Gm5849", 
"Mbl2", "Akap8", "Xrcc5", "Nfkb2", "Masp1", "Trim8", "Pcbp2", 
"Ppp1r14b", "Gsdmd", "Fer", "Grap2", "Nlrc4", "Map4k2"), external_gene_name = c("Uba7", 
"Ube2l6", "Ube2e1", "Ube2e2", "Isg15", "Ikbke", "Setd2", "A230050P20Rik", 
"Mx2", "Shmt2", "Irgm2", "Dnaja3", "Kynu", "Bst2", "Sec61a1", 
"Cited1", "H2-Aa", "Slc11a1", "Gch1", "Ubd", "Il23r", "Slc30a8", 
"Cxcl16", "Cyp27b1", "Trim21", "Ifitm2", "Ifitm1", "Ifitm3", 
"Adamts13", "Tgtp2", "Tgtp1", "Snca", "Cd40", "Mefv", "Ciita", 
"Klhl20", "Adar", "Ifnar2", "Eif2ak2", "Plscr1", "Lamp3", "Xaf1", 
"Stat1", "S100a8", "Trdc", "S100a9", "Aim2", "Mb21d1", "Irf1", 
"Pglyrp4", "Sdhaf4", "Ddx3x", "Defb1", "Serinc5", "Ddx58", "Defb12", 
"Defb34", "Nlrp10", "Rela", "Gata3", "Csf1r", "Igha", "Defb15", 
"Rnase6", "Defb35", "Defb13", "Pglyrp3", "Ighg2c", "Krt16", "Tril", 
"Nlrp9c", "Bpifb3", "Pik3ca", "Nlrp1a", "Nlrp9b", "Ighg3", "Ighd", 
"Ighm", "Nlrp1b", "Cfi", "Ly96", "Jchain", "C8b", "Nlrx1", "Cybb", 
"Pml", "C8a", "Tnk1", "Polr3c", "Il1rap", "Rbm14", "Polr3e", 
"Anxa1", "Cfd", "Ifnk", "Fcnb", "Nr1h4", "Defb43", "Nono", "5730559C18Rik", 
"Hmgb3", "Defb30", "Sh2d1b2", "Ighv5-2", "Ighv2-2", "Tnfaip8l2", 
"Tarm1", "Ighv5-4", "Bpifa1", "Nod2", "Ighv2-3", "Otulin", "Ighv5-6", 
"Bpifb1", "Ifi202b", "Ighv5-9", "Fcgr1", "Trim28", "Arg1", "Trbc1", 
"Pik3cg", "Defb18", "Defb41", "Ighv2-5", "Ighv5-12", "Ighv2-6", 
"Ighv5-9-1", "Polr3g", "Cyld", "Sh2d1a", "Zap70", "Ifit3", "Rsad2", 
"Msrb1", "Ifit1", "Cr1l", "Cfp", "Sp110", "Trbc2", "Casp4", "Nod1", 
"Sla2", "Smpdl3b", "Tlr5", "Ighv5-12-4", "Ighv2-9-1", "Axl", 
"Map3k5", "Cd55", "Blk", "Myd88", "Tnfsf4", "Ighv2-6-8", "Ighv2-7", 
"Ighv5-15", "Ighv5-16", "Ighv5-17", "Ighv2-9", "Irf5", "Ighv7-1", 
"Ighv7-2", "Ighv14-1", "Ighv4-1", "Ighv3-1", "Ighv11-1", "Trim11", 
"Sla", "Ighv14-2", "Ighv11-2", "Ighv14-3", "Trim14", "Ighv16-1", 
"Ighv9-1", "Dhx58", "Trim13", "Pqbp1", "Cyba", "Ighv9-2", "Ighv9-3", 
"Ighv7-3", "Ankhd1", "Ighv14-4", "Ighv3-3", "Oasl2", "Ighv7-4", 
"Ighv3-4", "Nrros", "Tlr13", "Fes", "Ticam1", "Ighv3-6", "Ighv9-4", 
"Apobec3", "Ighv3-8", "Ighv13-2", "Ankrd17", "Trim15", "Ighv12-3", 
"Ighv6-3", "Oasl1", "Trim10", "Tlr1", "Ighv6-4", "C4bp", "Trim5", 
"Tlr6", "Trim31", "Polr3b", "Mavs", "Vnn1", "Apcs", "Akirin2", 
"Ssc5d", "Trim12a", "Polr3d", "Clec5a", "Fgg", "Dab2ip", "Hmgb2", 
"Fga", "Fgb", "Trim12c", "Fgr", "Ipo7", "Mst1r", "Trim30b", "Trim30c", 
"Sfpq", "Il34", "Trim25", "Trim30a", "Trim30d", "Pspc1", "Card9", 
"Mbl1", "Ptk2", "Lcn2", "Abl1", "Sftpd", "Tlr8", "Pycard", "Ighv6-5", 
"Tlr2", "Ighv6-6", "Ighv6-7", "Serping1", "Tlr7", "Src", "Ighv8-2", 
"Iglc1", "Ighv10-1", "Ighv1-4", "Il1f6", "Iglc4", "Ighv1-5", 
"Ighv10-3", "Ighv1-7", "Iglc2", "Defb23", "Gper1", "Cnpy3", "Trdv4", 
"Defb20", "Defb22", "Defb26", "Defb28", "Il1f5", "Defb29", "Ighv15-2", 
"Ighv1-9", "Defb21", "Itch", "Pglyrp1", "Nfkb1", "Defb19", "Defb45", 
"Il1rl2", "Defb36", "Mid2", "Defb25", "Ighv1-11", "Ighv1-12", 
"Ighv1-15", "Ighv1-16", "Grb2", "Ighv1-18", "Ighv1-19", "Ighv1-20", 
"Map4k2", "Il1f8", "Pik3cb", "Adam15", "Ighv1-22", "Bcl10", "Ighv1-23", 
"Ighv1-24", "Ighv1-26", "Prkdc", "Irak4", "F2rl1", "Adgrb1", 
"Isg20", "C1qb", "C1qc", "C1qa", "Mr1", "Polr3a", "Tlr9", "Ighv1-76", 
"Optn", "Ighv1-77", "Ptx3", "Ighv1-78", "Zbtb1", "Grap", "Lbp", 
"Arhgef2", "Mcoln2", "Ighv1-80", "Tbk1", "Ighv1-81", "Ifih1", 
"Ighv1-31", "Bmx", "Ighv1-82", "Ighv1-34", "Ly86", "Nlrc5", "Ighv1-85", 
"Polr3f", "Ighv1-36", "Ighv1-37", "Tlr11", "Trim27", "Malt1", 
"Fadd", "Ighv1-39", "Ighv1-42", "Ighv1-43", "Btk", "Dcst1", "Parp14", 
"Ighv1-47", "Ighv8-4", "Ighv1-49", "Itk", "Ighv8-5", "Ighv1-50", 
"Trim26", "Chid1", "Csk", "Fcer1g", "Ighv1-52", "Ighv1-53", "Ighv8-6", 
"Naip2", "Nlrp3", "C8g", "Ighv1-54", "Csf1", "Traf3", "Ighv1-55", 
"Ighv1-56", "Elf4", "Dtx3l", "Irak1", "Naip6", "Parp9", "Ighv8-8", 
"Ighv1-58", "Pik3cd", "Hck", "Ighv1-59", "Cd180", "Irf3", "Ighv1-61", 
"Ighv1-62-1", "Ifnl2", "Relb", "Ifnl3", "Fyn", "Ighv1-62-2", 
"Ighv1-62-3", "Hmgb1", "Tlr12", "Ighv8-9", "Yes1", "Ighv1-63", 
"Ighv1-64", "Tbkbp1", "Siglecg", "Ighv8-11", "Ighv1-66", "Cfh", 
"Zc3hav1", "Ighv1-67", "Ighv1-69", "Ighv8-12", "Havcr2", "4933415F23Rik", 
"Trim32", "Ighv8-13", "C3", "Ighv1-74", "Trim62", "Hexim1", "Matr3", 
"Ighv1-75", "Slpi", "Zfp809", "Igll1", "Arid5a", "Tollip", "Tlr4", 
"Syk", "C4b", "Cd244", "Fbxo9", "Ly9", "Ifnb1", "Zfp683", "Ifna15", 
"Ifna9", "Ifna14", "Ifna12", "Lck", "Serinc3", "Nlrp6", "Camp", 
"Ifna13", "Ifna16", "Ifnab", "Lyn", "Gm13271", "Gm13283", "Gm13290", 
"Gm13289", "Gm13272", "Cd24a", "Spon2", "Lgr4", "Ifnz", "Gm13276", 
"Gm13277", "Gm13278", "Tlr3", "Gm13275", "Gm13279", "Gm13285", 
"Gm13287", "Gm13288", "Ifna11", "Ifna4", "Oas2", "Prkd1", "Oas3", 
"Slamf1", "Marco", "Ifne", "Rarres2", "Clec4a2", "Treml4", "Oas1a", 
"Slamf6", "Fcna", "Sarm1", "Atg5", "Trim59", "Clec4n", "Herc6", 
"Ripk2", "Irgm1", "Prdm1", "Hc", "Clec4d", "Clec4e", "Ticam2", 
"Trem2", "Il27", "Frk", "Mif", "Ptk2b", "C1rl", "Irf7", "C1ra", 
"C1rb", "C1s2", "Polr3k", "Zbp1", "Trim35", "Il23a", "C2", "Cfb", 
"Padi4", "Cactin", "Masp2", "Klrg1", "Arg2", "Ptk6", "Clec7a", 
"Rnf135", "Txk", "Klrk1", "Sec14l1", "Crcp", "Styk1", "Tmem173", 
"Atg12", "Gm17416", "Iigp1", "Polr3h", "Riok3", "Cd14", "Gm5849", 
"Mbl2", "Akap8", "Xrcc5", "Nfkb2", "Masp1", "Trim8", "Pcbp2", 
"Ppp1r14b", "Gsdmd", "Fer", "Grap2", "Nlrc4", "Map4k2"), ensembl_gene_id = c("ENSMUSG00000032596", 
"ENSMUSG00000027078", "ENSMUSG00000021774", "ENSMUSG00000058317", 
"ENSMUSG00000035692", "ENSMUSG00000042349", "ENSMUSG00000044791", 
"ENSMUSG00000038884", "ENSMUSG00000023341", "ENSMUSG00000025403", 
"ENSMUSG00000069874", "ENSMUSG00000004069", "ENSMUSG00000026866", 
"ENSMUSG00000046718", "ENSMUSG00000030082", "ENSMUSG00000051159", 
"ENSMUSG00000036594", "ENSMUSG00000026177", "ENSMUSG00000037580", 
"ENSMUSG00000035186", "ENSMUSG00000049093", "ENSMUSG00000022315", 
"ENSMUSG00000018920", "ENSMUSG00000006724", "ENSMUSG00000030966", 
"ENSMUSG00000060591", "ENSMUSG00000025491", "ENSMUSG00000025492", 
"ENSMUSG00000014852", "ENSMUSG00000078921", "ENSMUSG00000078922", 
"ENSMUSG00000025889", "ENSMUSG00000017652", "ENSMUSG00000022534", 
"ENSMUSG00000022504", "ENSMUSG00000026705", "ENSMUSG00000027951", 
"ENSMUSG00000022971", "ENSMUSG00000024079", "ENSMUSG00000032369", 
"ENSMUSG00000041247", "ENSMUSG00000040483", "ENSMUSG00000026104", 
"ENSMUSG00000056054", "ENSMUSG00000104876", "ENSMUSG00000056071", 
"ENSMUSG00000037860", "ENSMUSG00000032344", "ENSMUSG00000018899", 
"ENSMUSG00000042250", "ENSMUSG00000026154", "ENSMUSG00000000787", 
"ENSMUSG00000044748", "ENSMUSG00000021703", "ENSMUSG00000040296", 
"ENSMUSG00000043787", "ENSMUSG00000052554", "ENSMUSG00000049709", 
"ENSMUSG00000024927", "ENSMUSG00000015619", "ENSMUSG00000024621", 
"ENSMUSG00000095079", "ENSMUSG00000048500", "ENSMUSG00000021880", 
"ENSMUSG00000058052", "ENSMUSG00000044222", "ENSMUSG00000042244", 
"ENSMUSG00000076612", "ENSMUSG00000053797", "ENSMUSG00000043496", 
"ENSMUSG00000040614", "ENSMUSG00000068008", "ENSMUSG00000027665", 
"ENSMUSG00000069830", "ENSMUSG00000060508", "ENSMUSG00000076615", 
"ENSMUSG00000104213", "ENSMUSG00000076617", "ENSMUSG00000070390", 
"ENSMUSG00000058952", "ENSMUSG00000025779", "ENSMUSG00000067149", 
"ENSMUSG00000029656", "ENSMUSG00000032109", "ENSMUSG00000015340", 
"ENSMUSG00000036986", "ENSMUSG00000035031", "ENSMUSG00000001583", 
"ENSMUSG00000028099", "ENSMUSG00000022514", "ENSMUSG00000006456", 
"ENSMUSG00000030880", "ENSMUSG00000024659", "ENSMUSG00000061780", 
"ENSMUSG00000042993", "ENSMUSG00000026835", "ENSMUSG00000047638", 
"ENSMUSG00000075572", "ENSMUSG00000031311", "ENSMUSG00000041605", 
"ENSMUSG00000015217", "ENSMUSG00000075571", "ENSMUSG00000073494", 
"ENSMUSG00000076633", "ENSMUSG00000096464", "ENSMUSG00000013707", 
"ENSMUSG00000053338", "ENSMUSG00000095612", "ENSMUSG00000027483", 
"ENSMUSG00000055994", "ENSMUSG00000094164", "ENSMUSG00000046034", 
"ENSMUSG00000094951", "ENSMUSG00000027485", "ENSMUSG00000026535", 
"ENSMUSG00000095285", "ENSMUSG00000015947", "ENSMUSG00000005566", 
"ENSMUSG00000019987", "ENSMUSG00000076490", "ENSMUSG00000020573", 
"ENSMUSG00000073735", "ENSMUSG00000067773", "ENSMUSG00000096498", 
"ENSMUSG00000095429", "ENSMUSG00000096670", "ENSMUSG00000095210", 
"ENSMUSG00000035834", "ENSMUSG00000036712", "ENSMUSG00000005696", 
"ENSMUSG00000026117", "ENSMUSG00000074896", "ENSMUSG00000020641", 
"ENSMUSG00000075705", "ENSMUSG00000034459", "ENSMUSG00000016481", 
"ENSMUSG00000001128", "ENSMUSG00000070034", "ENSMUSG00000076498", 
"ENSMUSG00000033538", "ENSMUSG00000038058", "ENSMUSG00000027636", 
"ENSMUSG00000028885", "ENSMUSG00000079164", "ENSMUSG00000103033", 
"ENSMUSG00000095565", "ENSMUSG00000002602", "ENSMUSG00000071369", 
"ENSMUSG00000026399", "ENSMUSG00000014453", "ENSMUSG00000032508", 
"ENSMUSG00000026700", "ENSMUSG00000076646", "ENSMUSG00000096824", 
"ENSMUSG00000094134", "ENSMUSG00000094194", "ENSMUSG00000095571", 
"ENSMUSG00000096638", "ENSMUSG00000029771", "ENSMUSG00000076665", 
"ENSMUSG00000076653", "ENSMUSG00000094509", "ENSMUSG00000076655", 
"ENSMUSG00000093838", "ENSMUSG00000094533", "ENSMUSG00000020455", 
"ENSMUSG00000022372", "ENSMUSG00000095583", "ENSMUSG00000096108", 
"ENSMUSG00000095642", "ENSMUSG00000039853", "ENSMUSG00000076661", 
"ENSMUSG00000096805", "ENSMUSG00000017830", "ENSMUSG00000035235", 
"ENSMUSG00000031157", "ENSMUSG00000006519", "ENSMUSG00000094102", 
"ENSMUSG00000096459", "ENSMUSG00000076652", "ENSMUSG00000024483", 
"ENSMUSG00000076666", "ENSMUSG00000094029", "ENSMUSG00000029561", 
"ENSMUSG00000076668", "ENSMUSG00000103939", "ENSMUSG00000052384", 
"ENSMUSG00000033777", "ENSMUSG00000053158", "ENSMUSG00000047123", 
"ENSMUSG00000076672", "ENSMUSG00000094322", "ENSMUSG00000009585", 
"ENSMUSG00000076674", "ENSMUSG00000076671", "ENSMUSG00000055204", 
"ENSMUSG00000050747", "ENSMUSG00000076676", "ENSMUSG00000076677", 
"ENSMUSG00000041827", "ENSMUSG00000073400", "ENSMUSG00000044827", 
"ENSMUSG00000094174", "ENSMUSG00000026405", "ENSMUSG00000060441", 
"ENSMUSG00000051498", "ENSMUSG00000058063", "ENSMUSG00000034453", 
"ENSMUSG00000037523", "ENSMUSG00000037440", "ENSMUSG00000026542", 
"ENSMUSG00000028291", "ENSMUSG00000035279", "ENSMUSG00000066258", 
"ENSMUSG00000000776", "ENSMUSG00000029915", "ENSMUSG00000033860", 
"ENSMUSG00000026883", "ENSMUSG00000054717", "ENSMUSG00000028001", 
"ENSMUSG00000033831", "ENSMUSG00000057143", "ENSMUSG00000028874", 
"ENSMUSG00000066232", "ENSMUSG00000032584", "ENSMUSG00000052749", 
"ENSMUSG00000078616", "ENSMUSG00000028820", "ENSMUSG00000031750", 
"ENSMUSG00000000275", "ENSMUSG00000030921", "ENSMUSG00000057596", 
"ENSMUSG00000021938", "ENSMUSG00000026928", "ENSMUSG00000037780", 
"ENSMUSG00000022607", "ENSMUSG00000026822", "ENSMUSG00000026842", 
"ENSMUSG00000021795", "ENSMUSG00000040522", "ENSMUSG00000030793", 
"ENSMUSG00000096407", "ENSMUSG00000027995", "ENSMUSG00000076680", 
"ENSMUSG00000087582", "ENSMUSG00000023224", "ENSMUSG00000044583", 
"ENSMUSG00000027646", "ENSMUSG00000102301", "ENSMUSG00000105906", 
"ENSMUSG00000095981", "ENSMUSG00000095442", "ENSMUSG00000026984", 
"ENSMUSG00000106039", "ENSMUSG00000096499", "ENSMUSG00000095700", 
"ENSMUSG00000095200", "ENSMUSG00000076937", "ENSMUSG00000074681", 
"ENSMUSG00000053647", "ENSMUSG00000023973", "ENSMUSG00000076867", 
"ENSMUSG00000049560", "ENSMUSG00000027468", "ENSMUSG00000074680", 
"ENSMUSG00000074679", "ENSMUSG00000026983", "ENSMUSG00000044249", 
"ENSMUSG00000076688", "ENSMUSG00000094694", "ENSMUSG00000056544", 
"ENSMUSG00000027598", "ENSMUSG00000030413", "ENSMUSG00000028163", 
"ENSMUSG00000050645", "ENSMUSG00000062124", "ENSMUSG00000070942", 
"ENSMUSG00000044863", "ENSMUSG00000000266", "ENSMUSG00000074678", 
"ENSMUSG00000102888", "ENSMUSG00000095416", "ENSMUSG00000103254", 
"ENSMUSG00000095554", "ENSMUSG00000059923", "ENSMUSG00000076695", 
"ENSMUSG00000096410", "ENSMUSG00000095761", "ENSMUSG00000024948", 
"ENSMUSG00000026985", "ENSMUSG00000032462", "ENSMUSG00000028041", 
"ENSMUSG00000094561", "ENSMUSG00000028191", "ENSMUSG00000103290", 
"ENSMUSG00000094241", "ENSMUSG00000094546", "ENSMUSG00000022672", 
"ENSMUSG00000059883", "ENSMUSG00000021678", "ENSMUSG00000034730", 
"ENSMUSG00000039236", "ENSMUSG00000036905", "ENSMUSG00000036896", 
"ENSMUSG00000036887", "ENSMUSG00000026471", "ENSMUSG00000025280", 
"ENSMUSG00000045322", "ENSMUSG00000093896", "ENSMUSG00000026672", 
"ENSMUSG00000096452", "ENSMUSG00000027832", "ENSMUSG00000096326", 
"ENSMUSG00000033454", "ENSMUSG00000004837", "ENSMUSG00000016024", 
"ENSMUSG00000028059", "ENSMUSG00000011008", "ENSMUSG00000094075", 
"ENSMUSG00000020115", "ENSMUSG00000094689", "ENSMUSG00000026896", 
"ENSMUSG00000096649", "ENSMUSG00000031377", "ENSMUSG00000095127", 
"ENSMUSG00000093955", "ENSMUSG00000021423", "ENSMUSG00000074151", 
"ENSMUSG00000096150", "ENSMUSG00000027427", "ENSMUSG00000094051", 
"ENSMUSG00000095923", "ENSMUSG00000051969", "ENSMUSG00000021326", 
"ENSMUSG00000032688", "ENSMUSG00000031077", "ENSMUSG00000095130", 
"ENSMUSG00000094652", "ENSMUSG00000095859", "ENSMUSG00000031264", 
"ENSMUSG00000042672", "ENSMUSG00000034422", "ENSMUSG00000076709", 
"ENSMUSG00000096355", "ENSMUSG00000076710", "ENSMUSG00000020395", 
"ENSMUSG00000102364", "ENSMUSG00000094198", "ENSMUSG00000024457", 
"ENSMUSG00000025512", "ENSMUSG00000032312", "ENSMUSG00000058715", 
"ENSMUSG00000095204", "ENSMUSG00000093894", "ENSMUSG00000094505", 
"ENSMUSG00000078945", "ENSMUSG00000032691", "ENSMUSG00000015083", 
"ENSMUSG00000094787", "ENSMUSG00000014599", "ENSMUSG00000021277", 
"ENSMUSG00000095589", "ENSMUSG00000094862", "ENSMUSG00000031103", 
"ENSMUSG00000049502", "ENSMUSG00000031392", "ENSMUSG00000078942", 
"ENSMUSG00000022906", "ENSMUSG00000104452", "ENSMUSG00000095889", 
"ENSMUSG00000039936", "ENSMUSG00000003283", "ENSMUSG00000095197", 
"ENSMUSG00000021624", "ENSMUSG00000003184", "ENSMUSG00000094087", 
"ENSMUSG00000102313", "ENSMUSG00000059128", "ENSMUSG00000002983", 
"ENSMUSG00000060747", "ENSMUSG00000019843", "ENSMUSG00000096078", 
"ENSMUSG00000096767", "ENSMUSG00000066551", "ENSMUSG00000062545", 
"ENSMUSG00000095117", "ENSMUSG00000014932", "ENSMUSG00000096672", 
"ENSMUSG00000094088", "ENSMUSG00000038517", "ENSMUSG00000030468", 
"ENSMUSG00000095170", "ENSMUSG00000095519", "ENSMUSG00000026365", 
"ENSMUSG00000029826", "ENSMUSG00000095863", "ENSMUSG00000094502", 
"ENSMUSG00000076731", "ENSMUSG00000020399", "ENSMUSG00000073730", 
"ENSMUSG00000051675", "ENSMUSG00000076733", "ENSMUSG00000024164", 
"ENSMUSG00000094124", "ENSMUSG00000041000", "ENSMUSG00000048878", 
"ENSMUSG00000037236", "ENSMUSG00000096020", "ENSMUSG00000017002", 
"ENSMUSG00000057982", "ENSMUSG00000075370", "ENSMUSG00000037447", 
"ENSMUSG00000025139", "ENSMUSG00000039005", "ENSMUSG00000021457", 
"ENSMUSG00000073418", "ENSMUSG00000004709", "ENSMUSG00000001366", 
"ENSMUSG00000004707", "ENSMUSG00000048806", "ENSMUSG00000049410", 
"ENSMUSG00000096011", "ENSMUSG00000095270", "ENSMUSG00000095896", 
"ENSMUSG00000073811", "ENSMUSG00000000409", "ENSMUSG00000017707", 
"ENSMUSG00000038745", "ENSMUSG00000038357", "ENSMUSG00000063376", 
"ENSMUSG00000078355", "ENSMUSG00000100079", "ENSMUSG00000042228", 
"ENSMUSG00000094618", "ENSMUSG00000100505", "ENSMUSG00000094271", 
"ENSMUSG00000096582", "ENSMUSG00000096591", "ENSMUSG00000047139", 
"ENSMUSG00000037379", "ENSMUSG00000050199", "ENSMUSG00000096854", 
"ENSMUSG00000099545", "ENSMUSG00000100234", "ENSMUSG00000101163", 
"ENSMUSG00000031639", "ENSMUSG00000099518", "ENSMUSG00000099420", 
"ENSMUSG00000095101", "ENSMUSG00000094648", "ENSMUSG00000070908", 
"ENSMUSG00000100549", "ENSMUSG00000070904", "ENSMUSG00000032690", 
"ENSMUSG00000002688", "ENSMUSG00000032661", "ENSMUSG00000015316", 
"ENSMUSG00000026390", "ENSMUSG00000045364", "ENSMUSG00000009281", 
"ENSMUSG00000030148", "ENSMUSG00000051682", "ENSMUSG00000052776", 
"ENSMUSG00000015314", "ENSMUSG00000026938", "ENSMUSG00000050132", 
"ENSMUSG00000038160", "ENSMUSG00000034317", "ENSMUSG00000023349", 
"ENSMUSG00000029798", "ENSMUSG00000041135", "ENSMUSG00000046879", 
"ENSMUSG00000038151", "ENSMUSG00000026874", "ENSMUSG00000030144", 
"ENSMUSG00000030142", "ENSMUSG00000056130", "ENSMUSG00000023992", 
"ENSMUSG00000044701", "ENSMUSG00000019779", "ENSMUSG00000033307", 
"ENSMUSG00000059456", "ENSMUSG00000038527", "ENSMUSG00000025498", 
"ENSMUSG00000055172", "ENSMUSG00000098470", "ENSMUSG00000079343", 
"ENSMUSG00000038628", "ENSMUSG00000027514", "ENSMUSG00000022043", 
"ENSMUSG00000025383", "ENSMUSG00000024371", "ENSMUSG00000090231", 
"ENSMUSG00000025330", "ENSMUSG00000034889", "ENSMUSG00000028979", 
"ENSMUSG00000030114", "ENSMUSG00000021125", "ENSMUSG00000038751", 
"ENSMUSG00000079293", "ENSMUSG00000020707", "ENSMUSG00000054892", 
"ENSMUSG00000030149", "ENSMUSG00000020823", "ENSMUSG00000025532", 
"ENSMUSG00000032899", "ENSMUSG00000024349", "ENSMUSG00000032905", 
"ENSMUSG00000090485", "ENSMUSG00000054072", "ENSMUSG00000022476", 
"ENSMUSG00000024404", "ENSMUSG00000051439", "ENSMUSG00000096621", 
"ENSMUSG00000024863", "ENSMUSG00000024045", "ENSMUSG00000026187", 
"ENSMUSG00000025225", "ENSMUSG00000022887", "ENSMUSG00000025034", 
"ENSMUSG00000056851", "ENSMUSG00000056612", "ENSMUSG00000022575", 
"ENSMUSG00000000127", "ENSMUSG00000042351", "ENSMUSG00000039193", 
"ENSMUSG00000106850")), .Names = c("mgi_symbol", "external_gene_name", 
"ensembl_gene_id"), class = "data.frame", row.names = c(NA, -527L
))
results_interferon_response_immune

Run PCA and t-SNE for the young vs old SmartSeq2 data

seurat_sms2 <- FindVariableGenes(object = seurat_sms2, mean.function = ExpMean, dispersion.function = LogVMR, 
    y.cutoff = 0.75)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

genes.var <- apply(X = seurat_sms2@raw.data , MARGIN = 1 , FUN = var)
genes.var.top <- names( sort(genes.var , decreasing = TRUE)[1:2000] )
seurat_sms2@var.genes <- genes.var.top
seurat_sms2@imputed <- as.data.frame.matrix(seurat_sms2@data)
seurat_sms2 <- RunPCA(object = seurat_sms2, pc.genes = seurat_sms2@var.genes, do.print = TRUE, pcs.print = 1:5, genes.print = 5 , use.imputed = TRUE )
[1] "PC1"
[1] "ENSMUSG00000028517" "ENSMUSG00000022037" "ENSMUSG00000002985" "ENSMUSG00000079037" "ENSMUSG00000006205"
[1] ""
[1] "ENSMUSG00000094627" "ENSMUSG00000047945" "ENSMUSG00000020737" "ENSMUSG00000003038" "ENSMUSG00000049775"
[1] ""
[1] ""
[1] "PC2"
[1] "ENSMUSG00000026385" "ENSMUSG00000001025" "ENSMUSG00000026701" "ENSMUSG00000037852" "ENSMUSG00000018451"
[1] ""
[1] "ENSMUSG00000038943" "ENSMUSG00000020897" "ENSMUSG00000019942" "ENSMUSG00000005233" "ENSMUSG00000020914"
[1] ""
[1] ""
[1] "PC3"
[1] "ENSMUSG00000035202" "ENSMUSG00000031548" "ENSMUSG00000026728" "ENSMUSG00000086859" "ENSMUSG00000021702"
[1] ""
[1] "ENSMUSG00000010095" "ENSMUSG00000033998" "ENSMUSG00000039542" "ENSMUSG00000028691" "ENSMUSG00000031467"
[1] ""
[1] ""
[1] "PC4"
[1] "ENSMUSG00000030867" "ENSMUSG00000020897" "ENSMUSG00000020808" "ENSMUSG00000027496" "ENSMUSG00000030677"
[1] ""
[1] "ENSMUSG00000101249" "ENSMUSG00000100862" "ENSMUSG00000083563" "ENSMUSG00000101111" "ENSMUSG00000082179"
[1] ""
[1] ""
[1] "PC5"
[1] "ENSMUSG00000017677" "ENSMUSG00000030342" "ENSMUSG00000032046" "ENSMUSG00000097971" "ENSMUSG00000025381"
[1] ""
[1] "ENSMUSG00000057666" "ENSMUSG00000031762" "ENSMUSG00000028691" "ENSMUSG00000083076" "ENSMUSG00000035885"
[1] ""
[1] ""
seurat_sms2 <- ProjectPCA(object = seurat_sms2 )
[1] "PC1"
 [1] "ENSMUSG00000028517" "ENSMUSG00000022037" "ENSMUSG00000002985" "ENSMUSG00000079037" "ENSMUSG00000006205"
 [6] "ENSMUSG00000041329" "ENSMUSG00000050953" "ENSMUSG00000027447" "ENSMUSG00000026424" "ENSMUSG00000037706"
[11] "ENSMUSG00000031517" "ENSMUSG00000005360" "ENSMUSG00000017390" "ENSMUSG00000058254" "ENSMUSG00000045092"
[16] "ENSMUSG00000022132" "ENSMUSG00000029309" "ENSMUSG00000004892" "ENSMUSG00000020591" "ENSMUSG00000030428"
[21] "ENSMUSG00000028128" "ENSMUSG00000005089" "ENSMUSG00000027574" "ENSMUSG00000026249" "ENSMUSG00000031760"
[26] "ENSMUSG00000032883" "ENSMUSG00000007097" "ENSMUSG00000030310" "ENSMUSG00000022564" "ENSMUSG00000039533"
[1] ""
 [1] "ENSMUSG00000094627" "ENSMUSG00000047945" "ENSMUSG00000070713" "ENSMUSG00000020737" "ENSMUSG00000049775"
 [6] "ENSMUSG00000000184" "ENSMUSG00000003038" "ENSMUSG00000046434" "ENSMUSG00000001525" "ENSMUSG00000026238"
[11] "ENSMUSG00000096544" "ENSMUSG00000028832" "ENSMUSG00000079523" "ENSMUSG00000067274" "ENSMUSG00000094790"
[16] "ENSMUSG00000004530" "ENSMUSG00000015217" "ENSMUSG00000032518" "ENSMUSG00000054717" "ENSMUSG00000026355"
[21] "ENSMUSG00000028639" "ENSMUSG00000042462" "ENSMUSG00000002870" "ENSMUSG00000076437" "ENSMUSG00000049124"
[26] "ENSMUSG00000098318" "ENSMUSG00000006728" "ENSMUSG00000020649" "ENSMUSG00000044533" "ENSMUSG00000040274"
[1] ""
[1] ""
[1] "PC2"
 [1] "ENSMUSG00000026385" "ENSMUSG00000001025" "ENSMUSG00000027523" "ENSMUSG00000001270" "ENSMUSG00000018567"
 [6] "ENSMUSG00000026701" "ENSMUSG00000029446" "ENSMUSG00000018451" "ENSMUSG00000026728" "ENSMUSG00000029455"
[11] "ENSMUSG00000037852" "ENSMUSG00000076441" "ENSMUSG00000021702" "ENSMUSG00000053398" "ENSMUSG00000053931"
[16] "ENSMUSG00000024661" "ENSMUSG00000040997" "ENSMUSG00000030122" "ENSMUSG00000033059" "ENSMUSG00000024425"
[21] "ENSMUSG00000031839" "ENSMUSG00000068523" "ENSMUSG00000074457" "ENSMUSG00000067818" "ENSMUSG00000030934"
[26] "ENSMUSG00000044080" "ENSMUSG00000026185" "ENSMUSG00000031812" "ENSMUSG00000036854" "ENSMUSG00000031950"
[1] ""
 [1] "ENSMUSG00000070495" "ENSMUSG00000034120" "ENSMUSG00000085453" "ENSMUSG00000085334" "ENSMUSG00000002297"
 [6] "ENSMUSG00000102443" "ENSMUSG00000042501" "ENSMUSG00000096111" "ENSMUSG00000021998" "ENSMUSG00000056888"
[11] "ENSMUSG00000021097" "ENSMUSG00000102718" "ENSMUSG00000093684" "ENSMUSG00000092814" "ENSMUSG00000020717"
[16] "ENSMUSG00000069892" "ENSMUSG00000024411" "ENSMUSG00000075307" "ENSMUSG00000097452" "ENSMUSG00000085635"
[21] "ENSMUSG00000096061" "ENSMUSG00000040459" "ENSMUSG00000097156" "ENSMUSG00000097384" "ENSMUSG00000050097"
[26] "ENSMUSG00000010095" "ENSMUSG00000100131" "ENSMUSG00000036815" "ENSMUSG00000104174" "ENSMUSG00000025758"
[1] ""
[1] ""
[1] "PC3"
 [1] "ENSMUSG00000104211" "ENSMUSG00000102470" "ENSMUSG00000102858" "ENSMUSG00000035202" "ENSMUSG00000050097"
 [6] "ENSMUSG00000104069" "ENSMUSG00000026185" "ENSMUSG00000070495" "ENSMUSG00000086607" "ENSMUSG00000049723"
[11] "ENSMUSG00000096061" "ENSMUSG00000056888" "ENSMUSG00000042501" "ENSMUSG00000092814" "ENSMUSG00000093684"
[16] "ENSMUSG00000104329" "ENSMUSG00000017652" "ENSMUSG00000056025" "ENSMUSG00000096111" "ENSMUSG00000086189"
[21] "ENSMUSG00000081305" "ENSMUSG00000102599" "ENSMUSG00000014725" "ENSMUSG00000081974" "ENSMUSG00000036109"
[26] "ENSMUSG00000039982" "ENSMUSG00000101462" "ENSMUSG00000026728" "ENSMUSG00000027670" "ENSMUSG00000005493"
[1] ""
 [1] "ENSMUSG00000033998" "ENSMUSG00000010095" "ENSMUSG00000031467" "ENSMUSG00000036949" "ENSMUSG00000039542"
 [6] "ENSMUSG00000028691" "ENSMUSG00000057666" "ENSMUSG00000047557" "ENSMUSG00000022477" "ENSMUSG00000000088"
[11] "ENSMUSG00000030317" "ENSMUSG00000061904" "ENSMUSG00000021508" "ENSMUSG00000023456" "ENSMUSG00000003974"
[16] "ENSMUSG00000079592" "ENSMUSG00000048076" "ENSMUSG00000060424" "ENSMUSG00000058927" "ENSMUSG00000049612"
[21] "ENSMUSG00000028655" "ENSMUSG00000030235" "ENSMUSG00000033208" "ENSMUSG00000047786" "ENSMUSG00000032281"
[26] "ENSMUSG00000021613" "ENSMUSG00000032014" "ENSMUSG00000024091" "ENSMUSG00000023175" "ENSMUSG00000028757"
[1] ""
[1] ""
[1] "PC4"
 [1] "ENSMUSG00000041556" "ENSMUSG00000021702" "ENSMUSG00000036570" "ENSMUSG00000041577" "ENSMUSG00000053398"
 [6] "ENSMUSG00000027875" "ENSMUSG00000031137" "ENSMUSG00000018451" "ENSMUSG00000037003" "ENSMUSG00000031428"
[11] "ENSMUSG00000052188" "ENSMUSG00000059970" "ENSMUSG00000044550" "ENSMUSG00000027215" "ENSMUSG00000000346"
[16] "ENSMUSG00000037852" "ENSMUSG00000064220" "ENSMUSG00000024640" "ENSMUSG00000053931" "ENSMUSG00000030934"
[21] "ENSMUSG00000008393" "ENSMUSG00000066058" "ENSMUSG00000022489" "ENSMUSG00000021268" "ENSMUSG00000054400"
[26] "ENSMUSG00000022037" "ENSMUSG00000009281" "ENSMUSG00000046731" "ENSMUSG00000033059" "ENSMUSG00000015837"
[1] ""
 [1] "ENSMUSG00000101249" "ENSMUSG00000100862" "ENSMUSG00000083563" "ENSMUSG00000101111" "ENSMUSG00000082179"
 [6] "ENSMUSG00000083219" "ENSMUSG00000096449" "ENSMUSG00000102070" "ENSMUSG00000067736" "ENSMUSG00000081043"
[11] "ENSMUSG00000083076" "ENSMUSG00000100131" "ENSMUSG00000101939" "ENSMUSG00000096887" "ENSMUSG00000020122"
[16] "ENSMUSG00000083863" "ENSMUSG00000097346" "ENSMUSG00000074800" "ENSMUSG00000056612" "ENSMUSG00000067038"
[21] "ENSMUSG00000031320" "ENSMUSG00000086841" "ENSMUSG00000024387" "ENSMUSG00000049751" "ENSMUSG00000040722"
[26] "ENSMUSG00000035049" "ENSMUSG00000086583" "ENSMUSG00000081051" "ENSMUSG00000092902" "ENSMUSG00000100865"
[1] ""
[1] ""
[1] "PC5"
 [1] "ENSMUSG00000017677" "ENSMUSG00000030342" "ENSMUSG00000032046" "ENSMUSG00000027303" "ENSMUSG00000001467"
 [6] "ENSMUSG00000097971" "ENSMUSG00000025381" "ENSMUSG00000021670" "ENSMUSG00000022351" "ENSMUSG00000049339"
[11] "ENSMUSG00000021252" "ENSMUSG00000022122" "ENSMUSG00000019818" "ENSMUSG00000025203" "ENSMUSG00000027620"
[16] "ENSMUSG00000022199" "ENSMUSG00000020570" "ENSMUSG00000099615" "ENSMUSG00000030062" "ENSMUSG00000022812"
[21] "ENSMUSG00000031604" "ENSMUSG00000037608" "ENSMUSG00000030876" "ENSMUSG00000034126" "ENSMUSG00000024150"
[26] "ENSMUSG00000102918" "ENSMUSG00000020580" "ENSMUSG00000029778" "ENSMUSG00000093930" "ENSMUSG00000034210"
[1] ""
 [1] "ENSMUSG00000074280" "ENSMUSG00000057666" "ENSMUSG00000018509" "ENSMUSG00000082691" "ENSMUSG00000073002"
 [6] "ENSMUSG00000083911" "ENSMUSG00000031762" "ENSMUSG00000081254" "ENSMUSG00000028572" "ENSMUSG00000041115"
[11] "ENSMUSG00000028691" "ENSMUSG00000036246" "ENSMUSG00000075390" "ENSMUSG00000035885" "ENSMUSG00000082072"
[16] "ENSMUSG00000083076" "ENSMUSG00000097148" "ENSMUSG00000081964" "ENSMUSG00000039201" "ENSMUSG00000004610"
[21] "ENSMUSG00000066478" "ENSMUSG00000050856" "ENSMUSG00000095600" "ENSMUSG00000025486" "ENSMUSG00000060288"
[26] "ENSMUSG00000004085" "ENSMUSG00000022820" "ENSMUSG00000083564" "ENSMUSG00000022323" "ENSMUSG00000027835"
[1] ""
[1] ""
seurat_sms2 <- JackStraw(object = seurat_sms2  )
PCElbowPlot(object = seurat_sms2)

seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "type")
PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 2)

PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 3)

PCAPlot(object = seurat_sms2 , dim.1 = 2, dim.2 = 3)

seurat_sms2 <- RunTSNE(seurat_sms2, dims.use = c(1,2,3) , do.fast = T , seed.use = 1)
seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "type")
TSNEPlot(object = seurat_sms2)

seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "age")
TSNEPlot(object = seurat_sms2)

PCA plot PC1 vs PC2 with color

seurat_sms2@meta.data$type_long <- seurat_sms2@meta.data$type
seurat_sms2@meta.data$type_long <- recode_factor( seurat_sms2@meta.data$type_long , q1 = "qNSC1", q2 = "qNSC2", a1 = "aNSC1" , a2 = "aNSC2" )
seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "type_long")
PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 2 , cols.use = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , pt.shape = "age")

gg_pca <- PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 2 , cols.use = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , pt.shape = "age", do.return = TRUE)
gg_pca_2 <- ggplot(data = gg_pca$data , aes(x = x , y = y , color = ident , shape = pt.shape)) + geom_point() + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + scale_color_manual(values = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , limits = c("qNSC1","qNSC2","aNSC1","aNSC2") , "Activation state") + scale_shape_manual(values = c(old = 17 , young = 16) , "Age") + coord_equal() + xlab("PC1") + ylab("PC2")
print(gg_pca_2)

sd <-  GetDimReduction(object = seurat_sms2 , reduction.type = "pca" , slot = "sdev") 
pc_percentage_of_variance <- round( (sd^2/sum(sd^2))*100 , digits = 1 )
gg_pca_hollowcircle <- ggplot(data = gg_pca$data , aes(x = x , y = y , color = ident , shape = pt.shape)) + geom_point() + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + scale_color_manual(values = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , limits = c("qNSC1","qNSC2","aNSC1","aNSC2") , "Activation state") + scale_shape_manual(values = c(old = 17 , young = 1) , "Age") + coord_equal() + xlab( paste("PC1 (",pc_percentage_of_variance[1],"%)") ) + ylab( paste("PC2 (",pc_percentage_of_variance[2],"%)" )) + coord_equal()
print(gg_pca_hollowcircle)

gg_pca_3 <- ggplot(data = gg_pca$data , aes(x = x , y = y , fill = factor(ident, levels = c("qNSC1","qNSC2","aNSC1","aNSC2")) , shape = pt.shape) ) + geom_point(size = 2, color = "black" )  + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + scale_fill_manual(values = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , limits = c("qNSC1","qNSC2","aNSC1","aNSC2") , "Activation state") + scale_shape_manual(values = c(old = 24 , young = 21) , "Age") + coord_equal()  + xlab( paste("PC1 (",pc_percentage_of_variance[1],"%)") ) + ylab( paste("PC2 (",pc_percentage_of_variance[2],"%)" )) + guides(fill = guide_legend(override.aes=list(shape=21)))
print(gg_pca_3)

gg_pca_age <- ggplot(data = gg_pca$data , aes(x = x , y = y , fill = pt.shape , shape = pt.shape) ) + geom_point(size = 2, color = "black" )  + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + scale_fill_manual(values = c( "old" =  "slateblue", "young" = "yellowgreen") , labels = c( "old" , "young" ) , name = "Age" ) + scale_shape_manual(values = c(old = 24 , young = 21) , "Age") + coord_equal()  + xlab( paste("PC1 (",pc_percentage_of_variance[1],"%)") ) + ylab( paste("PC2 (",pc_percentage_of_variance[2],"%)" )) + guides(fill = guide_legend(override.aes=list(shape=21)))
print(gg_pca_age)

Make PCA plots for each subpopulation

age_colors <- c(young = "yellowgreen" , old = "slateblue")
PCAPlot_seurat <- function(object , dim1 = 1, dim2 = 2 , scale_pcs_by_sd = TRUE , pt.size = 2){
  gg_pca <- PCAPlot(object = object , dim.1 = dim1, dim.2 = dim2 , cols.use = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1") , pt.shape = "age", do.return = TRUE )
  
  sd <- GetDimReduction(object = object , reduction.type = "pca" , slot = "sdev")
  pov <- round( (sd^2/sum(sd^2))*100 , digits = 1 )
    
  if(scale_pcs_by_sd){
    gg_pca$data$x <- gg_pca$data$x * sd[[dim1]]
    gg_pca$data$y <- gg_pca$data$y * sd[[dim2]]
  }
  
  xlimits <- NULL
  ylimits <- NULL
    
  x_range <- range(gg_pca$data$x)
  x_diff <- x_range[2]-x_range[1] 
  
  y_range  <- range(gg_pca$data$y)
  y_diff <- y_range[2]-y_range[1] 
  if(x_diff > y_diff){
    
    offset <- (( x_diff - y_diff ) / 2 )
    
    y_range[1] <- y_range[1] - offset
    y_range[2] <- y_range[2] + offset
    ylimits <- y_range
        
  }else if( y_diff > x_diff ){
    
    offset <- (( y_diff - x_diff ) / 2 )
    
    x_range[1] <- x_range[1] - offset
    x_range[2] <- x_range[2] + offset
  
    xlimits <- x_range
    
  }
  
  gg <- ggplot(data = gg_pca$data , aes(x = x , y = y , fill = pt.shape , shape = pt.shape) ) + geom_point(size = pt.size, colour = "black") + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + scale_fill_manual(values = age_colors , limits = names(age_colors) , name = "Age") + scale_shape_manual(values = c(old = 24 , young = 21) , limits = names(age_colors) , name = "Age") + coord_equal()  + xlab(paste("PC",dim1," (",pov[dim1],"%)")) + ylab(paste("PC",dim2," (",pov[dim2], "%)")) + ggtitle(paste0(unique(gg_pca$data$ident)) ) + guides(color = "none")
  
  if(!is.null(xlimits)){gg <- gg + xlim( xlimits )}
  if(!is.null(ylimits)){gg <- gg + ylim( ylimits )}
  
  gg
}
TSNEPlot_Seurat <- function(x , title = ""){
  xlimits <- NULL
  ylimits <- NULL
    
  x_range <- range(x$tSNE_1)
  x_diff <- x_range[2]-x_range[1] 
  
  y_range  <- range(x$tSNE_2)
  y_diff <- y_range[2]-y_range[1] 
  if(x_diff > y_diff){
    
    offset <- (( x_diff - y_diff ) / 2 )
    
    y_range[1] <- y_range[1] - offset
    y_range[2] <- y_range[2] + offset
    ylimits <- y_range
        
  }else if( y_diff > x_diff ){
    
    offset <- (( y_diff - x_diff ) / 2 )
    
    x_range[1] <- x_range[1] - offset
    x_range[2] <- x_range[2] + offset
  
    xlimits <- x_range
  }
    
  gg <- ggplot(data = x , mapping = aes(x = tSNE_1 , y = tSNE_2 , fill = age  , shape = age)) + geom_point(size = 2, colour = "black") + scale_fill_manual(values = c( "old" =  "slateblue", "young" = "yellowgreen") , labels = c( "old" , "young" ) , name = "Age" ) + labs( x = "tSNE 1" , y = "tSNE 2" ) + coord_equal() + guides(color = "none") + scale_shape_manual(values = c( "old" = 24 , "young" = 21) , labels = c( "old" , "young" ) , name = "Age") + ggtitle( title )
  
  if(!is.null(xlimits)){gg <- gg + xlim( xlimits )}
  if(!is.null(ylimits)){gg <- gg + ylim( ylimits )}
  
  gg
}

qNSC1

seurat_sms2_qNSC1 <- SubsetData(object = seurat_sms2 , ident.use = "qNSC1")
seurat_sms2_qNSC1 <- FindVariableGenes(object = seurat_sms2_qNSC1 , mean.function = ExpMean, dispersion.function = LogVMR)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

seurat_sms2_qNSC1 <- RunPCA(object = seurat_sms2_qNSC1 , do.print = FALSE )
pca_q1 <- PCAPlot_seurat( object = seurat_sms2_qNSC1 , dim1 = 1, dim2 = 2 )
pca_q1

PCAPlot_seurat( object = seurat_sms2_qNSC1 , dim1 = 2, dim2 = 3 )

PC_top50genes_qNSC1<- bind_cols( lapply( list(PC1 = 1, PC2 = 2 , PC3 = 3) ,  FUN=function(x){PCTopGenes(object = seurat_sms2_qNSC1 , pc.use = x , num.genes = 50 )} ) )
PCElbowPlot(object = seurat_sms2_qNSC1)

seurat_sms2_qNSC1 <- RunTSNE(object = seurat_sms2_qNSC1 , dims.use = 1:4 , seed.use = 1 )
TSNEPlot(object = seurat_sms2_qNSC1 ) 

x <- FetchData( object =  seurat_sms2_qNSC1 , vars.all = c("tSNE_1","tSNE_2","age") )
gg_tsne_qNSC1 <- TSNEPlot_Seurat(x = x , title = "qNSC1") 
gg_tsne_qNSC1

qNSC2

seurat_sms2_qNSC2 <- SubsetData(object = seurat_sms2 , ident.use = "qNSC2")
seurat_sms2_qNSC2 <- FindVariableGenes(object = seurat_sms2_qNSC2 , mean.function = ExpMean, dispersion.function = LogVMR)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

seurat_sms2_qNSC2 <- RunPCA(object = seurat_sms2_qNSC2 , do.print = FALSE)
You're computing a large percentage of total singular values, standard svd might work better!
pca_q2 <- PCAPlot_seurat( object = seurat_sms2_qNSC2 , dim1 = 1, dim2 = 2 )
pca_q2

PCAPlot_seurat( object = seurat_sms2_qNSC2 , dim1 = 2, dim2 = 3 )

PC_top50genes_qNSC2<- bind_cols( lapply( list(PC1 = 1, PC2 = 2 , PC3 = 3) ,  FUN=function(x){PCTopGenes(object = seurat_sms2_qNSC2 , pc.use = x , num.genes = 50 )} ) )
PCElbowPlot(object = seurat_sms2_qNSC2)

seurat_sms2_qNSC2 <- RunTSNE(object = seurat_sms2_qNSC2 , dims.use = 1:5 , seed.use = 1 , perplexity = 13 )
TSNEPlot(object = seurat_sms2_qNSC2 ) 

x <- FetchData( object =  seurat_sms2_qNSC2 , vars.all = c("tSNE_1","tSNE_2","age") )
gg_tsne_qNSC2 <- TSNEPlot_Seurat(x = x , title = "qNSC2 (perplexity = 13)") 
gg_tsne_qNSC2

aNSC1

seurat_sms2_aNSC1 <- SubsetData(object = seurat_sms2 , ident.use = "aNSC1")
seurat_sms2_aNSC1 <- FindVariableGenes(object = seurat_sms2_aNSC1 , mean.function = ExpMean, dispersion.function = LogVMR)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

seurat_sms2_aNSC1 <- RunPCA(object = seurat_sms2_aNSC1 , do.print = FALSE)
You're computing a large percentage of total singular values, standard svd might work better!
pca_a1 <- PCAPlot_seurat( object = seurat_sms2_aNSC1 , dim1 = 1, dim2 = 2 )
pca_a1

PCAPlot_seurat( object = seurat_sms2_aNSC1 , dim1 = 2, dim2 = 3 )

PC_top50genes_aNSC1<- bind_cols( lapply( list(PC1 = 1, PC2 = 2 , PC3 = 3) ,  FUN=function(x){PCTopGenes(object = seurat_sms2_aNSC1 , pc.use = x , num.genes = 50 )} ) )
PCElbowPlot(object = seurat_sms2_aNSC1)

seurat_sms2_aNSC1 <- RunTSNE(object = seurat_sms2_aNSC1 , dims.use = 1:5 , seed.use = 1 , perplexity = 7 )
TSNEPlot(object = seurat_sms2_aNSC1 ) 

x <- FetchData( object =  seurat_sms2_aNSC1 , vars.all = c("tSNE_1","tSNE_2","age") )
gg_tsne_aNSC1 <- TSNEPlot_Seurat(x = x , title = "aNSC1 (perplexity = 7)") 
gg_tsne_aNSC1

aNSC2

seurat_sms2_aNSC2 <- SubsetData(object = seurat_sms2 , ident.use = "aNSC2")
seurat_sms2_aNSC2 <- FindVariableGenes(object = seurat_sms2_aNSC2 , mean.function = ExpMean, dispersion.function = LogVMR)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

seurat_sms2_aNSC2 <- RunPCA(object = seurat_sms2_aNSC2 , do.print = FALSE)
You're computing a large percentage of total singular values, standard svd might work better!
pca_a2 <- PCAPlot_seurat( object = seurat_sms2_aNSC2 , dim1 = 1, dim2 = 2 )
pca_a2

PCAPlot_seurat( object = seurat_sms2_aNSC2 , dim1 = 2, dim2 = 3 )

PC_top50genes_aNSC2<- bind_cols( lapply( list(PC1 = 1, PC2 = 2 , PC3 = 3) ,  FUN=function(x){PCTopGenes(object = seurat_sms2_aNSC2 , pc.use = x , num.genes = 50 )} ) )
PCElbowPlot(object = seurat_sms2_aNSC2)

seurat_sms2_aNSC2 <- RunTSNE(object = seurat_sms2_aNSC2 , dims.use = 1:5 , seed.use = 1 , perplexity = 7 )
TSNEPlot(object = seurat_sms2_aNSC2 ) 

x <- FetchData( object =  seurat_sms2_aNSC2 , vars.all = c("tSNE_1","tSNE_2","age") )
gg_tsne_aNSC2 <- TSNEPlot_Seurat(x = x , title = "aNSC2 (perplexity = 7)") 
gg_tsne_aNSC2

grid.arrange(pca_q1,pca_q2,pca_a1,pca_a2)

t-SNE plots of subpopulations

Gather all t-SNE plots

grid.arrange( gg_tsne_qNSC1 , gg_tsne_qNSC2 , gg_tsne_aNSC1 , gg_tsne_aNSC2 )

saveRDS(object = seurat_sms2 , file = "seurat_sms2.RDS" )

Find celltype markers

seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "type_long")
celltype_markers <- FindAllMarkers(object = seurat_sms2 ,test.use = "t" , random.seed = 123 )

   |+                                                 | 1 % ~32s          
   |++                                                | 2 % ~27s          
   |++                                                | 3 % ~26s          
   |+++                                               | 4 % ~24s          
   |+++                                               | 5 % ~23s          
   |++++                                              | 6 % ~23s          
   |++++                                              | 7 % ~22s          
   |+++++                                             | 8 % ~22s          
   |+++++                                             | 9 % ~21s          
   |++++++                                            | 10% ~21s          
   |++++++                                            | 11% ~21s          
   |+++++++                                           | 12% ~20s          
   |+++++++                                           | 13% ~20s          
   |++++++++                                          | 14% ~20s          
   |++++++++                                          | 15% ~19s          
   |+++++++++                                         | 16% ~19s          
   |+++++++++                                         | 17% ~19s          
   |++++++++++                                        | 18% ~19s          
   |++++++++++                                        | 19% ~18s          
   |+++++++++++                                       | 20% ~18s          
   |+++++++++++                                       | 21% ~18s          
   |++++++++++++                                      | 22% ~18s          
   |++++++++++++                                      | 23% ~17s          
   |+++++++++++++                                     | 24% ~17s          
   |+++++++++++++                                     | 25% ~17s          
   |++++++++++++++                                    | 26% ~17s          
   |++++++++++++++                                    | 27% ~16s          
   |+++++++++++++++                                   | 28% ~16s          
   |+++++++++++++++                                   | 29% ~16s          
   |++++++++++++++++                                  | 30% ~16s          
   |++++++++++++++++                                  | 31% ~15s          
   |+++++++++++++++++                                 | 32% ~15s          
   |+++++++++++++++++                                 | 33% ~15s          
   |++++++++++++++++++                                | 34% ~15s          
   |++++++++++++++++++                                | 35% ~14s          
   |+++++++++++++++++++                               | 36% ~14s          
   |+++++++++++++++++++                               | 37% ~14s          
   |++++++++++++++++++++                              | 38% ~14s          
   |++++++++++++++++++++                              | 39% ~14s          
   |+++++++++++++++++++++                             | 40% ~13s          
   |+++++++++++++++++++++                             | 41% ~13s          
   |++++++++++++++++++++++                            | 42% ~13s          
   |++++++++++++++++++++++                            | 43% ~13s          
   |+++++++++++++++++++++++                           | 44% ~12s          
   |+++++++++++++++++++++++                           | 45% ~12s          
   |++++++++++++++++++++++++                          | 46% ~12s          
   |++++++++++++++++++++++++                          | 47% ~12s          
   |+++++++++++++++++++++++++                         | 48% ~11s          
   |+++++++++++++++++++++++++                         | 49% ~11s          
   |++++++++++++++++++++++++++                        | 51% ~11s          
   |++++++++++++++++++++++++++                        | 52% ~11s          
   |+++++++++++++++++++++++++++                       | 53% ~11s          
   |+++++++++++++++++++++++++++                       | 54% ~10s          
   |++++++++++++++++++++++++++++                      | 55% ~10s          
   |++++++++++++++++++++++++++++                      | 56% ~10s          
   |+++++++++++++++++++++++++++++                     | 57% ~10s          
   |+++++++++++++++++++++++++++++                     | 58% ~09s          
   |++++++++++++++++++++++++++++++                    | 59% ~09s          
   |++++++++++++++++++++++++++++++                    | 60% ~09s          
   |+++++++++++++++++++++++++++++++                   | 61% ~09s          
   |+++++++++++++++++++++++++++++++                   | 62% ~09s          
   |++++++++++++++++++++++++++++++++                  | 63% ~08s          
   |++++++++++++++++++++++++++++++++                  | 64% ~08s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~08s          
   |+++++++++++++++++++++++++++++++++                 | 66% ~08s          
   |++++++++++++++++++++++++++++++++++                | 67% ~07s          
   |++++++++++++++++++++++++++++++++++                | 68% ~07s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~07s          
   |+++++++++++++++++++++++++++++++++++               | 70% ~07s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~07s          
   |++++++++++++++++++++++++++++++++++++              | 72% ~06s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~06s          
   |+++++++++++++++++++++++++++++++++++++             | 74% ~06s          
   |++++++++++++++++++++++++++++++++++++++            | 75% ~06s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~05s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~05s          
   |+++++++++++++++++++++++++++++++++++++++           | 78% ~05s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~05s          
   |++++++++++++++++++++++++++++++++++++++++          | 80% ~05s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 22s

   |+                                                 | 1 % ~27s          
   |+                                                 | 2 % ~27s          
   |++                                                | 3 % ~27s          
   |++                                                | 4 % ~27s          
   |+++                                               | 5 % ~26s          
   |+++                                               | 6 % ~26s          
   |++++                                              | 7 % ~26s          
   |++++                                              | 8 % ~26s          
   |+++++                                             | 9 % ~25s          
   |+++++                                             | 10% ~25s          
   |++++++                                            | 11% ~25s          
   |++++++                                            | 12% ~25s          
   |+++++++                                           | 13% ~24s          
   |+++++++                                           | 14% ~24s          
   |++++++++                                          | 15% ~24s          
   |++++++++                                          | 16% ~24s          
   |+++++++++                                         | 17% ~23s          
   |+++++++++                                         | 18% ~23s          
   |++++++++++                                        | 19% ~23s          
   |++++++++++                                        | 20% ~22s          
   |+++++++++++                                       | 21% ~22s          
   |+++++++++++                                       | 22% ~22s          
   |++++++++++++                                      | 23% ~22s          
   |++++++++++++                                      | 24% ~21s          
   |+++++++++++++                                     | 25% ~21s          
   |+++++++++++++                                     | 26% ~21s          
   |++++++++++++++                                    | 27% ~20s          
   |++++++++++++++                                    | 28% ~20s          
   |+++++++++++++++                                   | 29% ~20s          
   |+++++++++++++++                                   | 30% ~20s          
   |++++++++++++++++                                  | 31% ~19s          
   |++++++++++++++++                                  | 32% ~19s          
   |+++++++++++++++++                                 | 33% ~19s          
   |+++++++++++++++++                                | 34% ~19s          
   |++++++++++++++++++                                | 35% ~18s          
   |++++++++++++++++++                                | 36% ~18s          
   |+++++++++++++++++++                               | 37% ~18s          
   |+++++++++++++++++++                               | 38% ~17s          
   |++++++++++++++++++++                              | 39% ~17s          
   |++++++++++++++++++++                              | 40% ~17s          
   |+++++++++++++++++++++                             | 41% ~17s          
   |+++++++++++++++++++++                             | 42% ~16s          
   |++++++++++++++++++++++                            | 43% ~16s          
   |++++++++++++++++++++++                            | 44% ~16s          
   |+++++++++++++++++++++++                           | 45% ~15s          
   |+++++++++++++++++++++++                           | 46% ~15s          
   |++++++++++++++++++++++++                          | 47% ~15s          
   |++++++++++++++++++++++++                          | 48% ~15s          
   |+++++++++++++++++++++++++                         | 49% ~14s          
   |+++++++++++++++++++++++++                         | 50% ~14s          
   |++++++++++++++++++++++++++                        | 51% ~14s          
   |++++++++++++++++++++++++++                        | 52% ~13s          
   |+++++++++++++++++++++++++++                       | 53% ~13s          
   |+++++++++++++++++++++++++++                       | 54% ~13s          
   |++++++++++++++++++++++++++++                      | 55% ~13s          
   |++++++++++++++++++++++++++++                     | 56% ~12s          
   |+++++++++++++++++++++++++++++                     | 57% ~12s          
   |+++++++++++++++++++++++++++++                     | 58% ~12s          
   |++++++++++++++++++++++++++++++                    | 59% ~12s          
   |++++++++++++++++++++++++++++++                    | 60% ~11s          
   |+++++++++++++++++++++++++++++++                   | 61% ~11s          
   |+++++++++++++++++++++++++++++++                   | 62% ~11s          
   |++++++++++++++++++++++++++++++++                  | 63% ~10s          
   |++++++++++++++++++++++++++++++++                  | 64% ~10s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~10s          
   |+++++++++++++++++++++++++++++++++                 | 66% ~10s          
   |++++++++++++++++++++++++++++++++++                | 67% ~09s          
   |++++++++++++++++++++++++++++++++++               | 68% ~09s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~09s          
   |+++++++++++++++++++++++++++++++++++               | 70% ~08s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~08s          
   |++++++++++++++++++++++++++++++++++++              | 72% ~08s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~08s          
   |+++++++++++++++++++++++++++++++++++++             | 74% ~07s          
   |++++++++++++++++++++++++++++++++++++++            | 75% ~07s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~07s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~06s          
   |+++++++++++++++++++++++++++++++++++++++          | 78% ~06s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~06s          
   |++++++++++++++++++++++++++++++++++++++++         | 80% ~06s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~05s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~05s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~05s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~05s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++++    | 90% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++++   | 92% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 28s

   |+                                                 | 1 % ~20s          
   |++                                                | 2 % ~20s          
   |++                                                | 3 % ~20s          
   |+++                                               | 4 % ~20s          
   |+++                                               | 5 % ~20s          
   |++++                                              | 6 % ~19s          
   |++++                                              | 7 % ~19s          
   |+++++                                             | 8 % ~19s          
   |+++++                                             | 9 % ~19s          
   |++++++                                            | 10% ~19s          
   |++++++                                            | 11% ~18s          
   |+++++++                                           | 12% ~18s          
   |+++++++                                           | 13% ~18s          
   |++++++++                                          | 14% ~18s          
   |++++++++                                          | 15% ~17s          
   |+++++++++                                         | 16% ~17s          
   |+++++++++                                         | 17% ~17s          
   |++++++++++                                        | 18% ~17s          
   |++++++++++                                        | 19% ~17s          
   |+++++++++++                                       | 20% ~17s          
   |+++++++++++                                       | 21% ~16s          
   |++++++++++++                                      | 22% ~16s          
   |++++++++++++                                      | 23% ~16s          
   |+++++++++++++                                     | 24% ~16s          
   |+++++++++++++                                     | 26% ~15s          
   |++++++++++++++                                    | 27% ~15s          
   |++++++++++++++                                    | 28% ~15s          
   |+++++++++++++++                                   | 29% ~15s          
   |+++++++++++++++                                   | 30% ~15s          
   |++++++++++++++++                                  | 31% ~14s          
   |++++++++++++++++                                  | 32% ~14s          
   |+++++++++++++++++                                 | 33% ~14s          
   |+++++++++++++++++                                 | 34% ~14s          
   |++++++++++++++++++                                | 35% ~14s          
   |++++++++++++++++++                                | 36% ~13s          
   |+++++++++++++++++++                               | 37% ~13s          
   |+++++++++++++++++++                               | 38% ~13s          
   |++++++++++++++++++++                              | 39% ~13s          
   |++++++++++++++++++++                              | 40% ~13s          
   |+++++++++++++++++++++                             | 41% ~12s          
   |+++++++++++++++++++++                             | 42% ~12s          
   |++++++++++++++++++++++                            | 43% ~12s          
   |++++++++++++++++++++++                            | 44% ~12s          
   |+++++++++++++++++++++++                           | 45% ~12s          
   |+++++++++++++++++++++++                           | 46% ~11s          
   |++++++++++++++++++++++++                          | 47% ~11s          
   |++++++++++++++++++++++++                          | 48% ~11s          
   |+++++++++++++++++++++++++                         | 49% ~11s          
   |+++++++++++++++++++++++++                         | 50% ~10s          
   |++++++++++++++++++++++++++                        | 51% ~10s          
   |+++++++++++++++++++++++++++                       | 52% ~10s          
   |+++++++++++++++++++++++++++                       | 53% ~10s          
   |++++++++++++++++++++++++++++                      | 54% ~10s          
   |++++++++++++++++++++++++++++                      | 55% ~09s          
   |+++++++++++++++++++++++++++++                     | 56% ~09s          
   |+++++++++++++++++++++++++++++                     | 57% ~09s          
   |++++++++++++++++++++++++++++++                    | 58% ~09s          
   |++++++++++++++++++++++++++++++                    | 59% ~09s          
   |+++++++++++++++++++++++++++++++                   | 60% ~08s          
   |+++++++++++++++++++++++++++++++                   | 61% ~08s          
   |++++++++++++++++++++++++++++++++                  | 62% ~08s          
   |++++++++++++++++++++++++++++++++                  | 63% ~08s          
   |+++++++++++++++++++++++++++++++++                 | 64% ~08s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~07s          
   |++++++++++++++++++++++++++++++++++                | 66% ~07s          
   |++++++++++++++++++++++++++++++++++                | 67% ~07s          
   |+++++++++++++++++++++++++++++++++++               | 68% ~07s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~06s          
   |++++++++++++++++++++++++++++++++++++              | 70% ~06s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~06s          
   |+++++++++++++++++++++++++++++++++++++             | 72% ~06s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~06s          
   |++++++++++++++++++++++++++++++++++++++            | 74% ~05s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~05s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~05s          
   |+++++++++++++++++++++++++++++++++++++++           | 78% ~05s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~05s          
   |++++++++++++++++++++++++++++++++++++++++          | 80% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 21s

   |+                                                 | 1 % ~09s          
   |++                                                | 2 % ~08s          
   |++                                                | 3 % ~08s          
   |+++                                               | 4 % ~08s          
   |+++                                               | 5 % ~08s          
   |++++                                              | 6 % ~08s          
   |++++                                              | 7 % ~08s          
   |+++++                                             | 8 % ~08s          
   |+++++                                             | 9 % ~08s          
   |++++++                                            | 10% ~08s          
   |++++++                                            | 11% ~08s          
   |+++++++                                           | 12% ~08s          
   |+++++++                                           | 13% ~08s          
   |++++++++                                          | 14% ~08s          
   |++++++++                                          | 15% ~07s          
   |+++++++++                                         | 16% ~07s          
   |+++++++++                                         | 17% ~07s          
   |++++++++++                                        | 18% ~07s          
   |++++++++++                                        | 19% ~07s          
   |+++++++++++                                       | 20% ~07s          
   |+++++++++++                                       | 21% ~07s          
   |++++++++++++                                      | 22% ~07s          
   |++++++++++++                                      | 23% ~07s          
   |+++++++++++++                                     | 24% ~07s          
   |+++++++++++++                                     | 25% ~06s          
   |++++++++++++++                                    | 26% ~06s          
   |++++++++++++++                                    | 27% ~06s          
   |+++++++++++++++                                   | 28% ~06s          
   |+++++++++++++++                                   | 29% ~06s          
   |++++++++++++++++                                  | 30% ~06s          
   |++++++++++++++++                                  | 31% ~06s          
   |+++++++++++++++++                                 | 32% ~06s          
   |+++++++++++++++++                                 | 33% ~06s          
   |++++++++++++++++++                                | 34% ~06s          
   |++++++++++++++++++                                | 35% ~06s          
   |+++++++++++++++++++                               | 36% ~06s          
   |+++++++++++++++++++                               | 37% ~05s          
   |++++++++++++++++++++                              | 38% ~05s          
   |++++++++++++++++++++                              | 39% ~05s          
   |+++++++++++++++++++++                             | 40% ~05s          
   |+++++++++++++++++++++                             | 41% ~05s          
   |++++++++++++++++++++++                            | 42% ~05s          
   |++++++++++++++++++++++                            | 43% ~05s          
   |+++++++++++++++++++++++                           | 44% ~05s          
   |+++++++++++++++++++++++                           | 45% ~05s          
   |++++++++++++++++++++++++                          | 46% ~05s          
   |++++++++++++++++++++++++                          | 47% ~05s          
   |+++++++++++++++++++++++++                         | 48% ~04s          
   |+++++++++++++++++++++++++                         | 49% ~04s          
   |++++++++++++++++++++++++++                        | 51% ~04s          
   |++++++++++++++++++++++++++                        | 52% ~04s          
   |+++++++++++++++++++++++++++                       | 53% ~04s          
   |+++++++++++++++++++++++++++                       | 54% ~04s          
   |++++++++++++++++++++++++++++                      | 55% ~04s          
   |++++++++++++++++++++++++++++                      | 56% ~04s          
   |+++++++++++++++++++++++++++++                     | 57% ~04s          
   |+++++++++++++++++++++++++++++                     | 58% ~04s          
   |++++++++++++++++++++++++++++++                    | 59% ~04s          
   |++++++++++++++++++++++++++++++                    | 60% ~03s          
   |+++++++++++++++++++++++++++++++                   | 61% ~03s          
   |+++++++++++++++++++++++++++++++                   | 62% ~03s          
   |++++++++++++++++++++++++++++++++                  | 63% ~03s          
   |++++++++++++++++++++++++++++++++                  | 64% ~03s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~03s          
   |+++++++++++++++++++++++++++++++++                 | 66% ~03s          
   |++++++++++++++++++++++++++++++++++                | 67% ~03s          
   |++++++++++++++++++++++++++++++++++                | 68% ~03s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~03s          
   |+++++++++++++++++++++++++++++++++++               | 70% ~03s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~03s          
   |++++++++++++++++++++++++++++++++++++              | 72% ~02s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~02s          
   |+++++++++++++++++++++++++++++++++++++             | 74% ~02s          
   |++++++++++++++++++++++++++++++++++++++            | 75% ~02s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~02s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~02s          
   |+++++++++++++++++++++++++++++++++++++++           | 78% ~02s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~02s          
   |++++++++++++++++++++++++++++++++++++++++          | 80% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~01s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 09s
celltype_markers

Save markers of individual celltypes

celltypes <- c("qNSC1","qNSC2","aNSC1","aNSC2")
for(i in celltypes){
  write.csv(x = celltype_markers %>% filter(cluster == i) , file = file.path("celltype_markers/",paste0("celltype_markers_",i,"_SmartSeq2.csv")) )
}

GO analysis clusterCompare celltypes

DE_results_list <- list()
for(i in celltypes){
  DE_results_list[[i]] <- celltype_markers %>% filter(cluster == i) 
}

GO term analysis function

GO_analysis <- function(DE_results_list , p_adj_cutoff = 0.05  ){
  require("clusterProfiler")
  
  if( length(DE_results_list) < 1){
    warning("No entries in DE_results_list")
    invisible(DE_results_list)
  }
  
  de_genes_list <-list(NULL)
  for(i in seq_len(length(DE_results_list)) ){
    de_genes <- DE_results_list[[i]] %>% filter( avg_logFC > 0 ) %>% dplyr::filter( p_val_adj < p_adj_cutoff ) %>% dplyr::pull(gene)
    
    de_genes_list[[ names(DE_results_list[i]) ]] <- bitr(geneID = de_genes , fromType = "ENSEMBL" , toType = "ENTREZID" , OrgDb = "org.Mm.eg.db" )[,"ENTREZID"]
  }
    # available ontologies are:
    # BP - biological_process
    # CC - cellular_component
    # MF - molecular_function
    go_results <- compareCluster(geneClusters = de_genes_list , fun = "enrichGO" , OrgDb = "org.Mm.eg.db" , ont = "BP", pvalueCutoff = 0.05 )
      
  return(go_results)
}
smartseq2_compare_GO_results <- GO_analysis(DE_results_list = DE_results_list , p_adj_cutoff = 0.01)
'select()' returned 1:many mapping between keys and columns
1.18% of input gene IDs are fail to map...'select()' returned 1:1 mapping between keys and columns
'select()' returned 1:many mapping between keys and columns
7% of input gene IDs are fail to map...'select()' returned 1:many mapping between keys and columns
3.31% of input gene IDs are fail to map...
dotplot( smartseq2_compare_GO_results , showCategory = 10)

smartseq2_compare_GO_results.sim <- clusterProfiler::simplify(smartseq2_compare_GO_results) 
gg2 <- clusterProfiler::dotplot(smartseq2_compare_GO_results , showCategory = 15)
gg2$data$Description <- fct_relabel( .f = gg2$data$Description , .fun = function(x){str_wrap(string = x , width = 40)} )
plotdata <- gg2$data %>% filter( p.adjust < 0.05)
levels(plotdata$Cluster) <- sub( x = levels(plotdata$Cluster) , pattern = "DE_celltype_genes_", replacement = "")
gg_clusterCompare <- ggplot(data = plotdata , mapping = aes( x = Cluster , y = Description , size = GeneRatio , color = -log10(p.adjust) ) ) + 
  geom_point() + 
  scale_color_gradient(low = "blue" , high = "red"  , breaks = c(1,10,20,30,40,50,60) , limits = c(1,60) ) + 
  theme_bw() + 
  theme( axis.text.x = element_text(colour="black",size=11), axis.text.y = element_text(colour="black",size=11, hjust = 1 ) )
gg_clusterCompare

gg_clusterCompare_center <- ggplot(data = plotdata , mapping = aes( x = Cluster , y = Description , size = GeneRatio , color = -log10(p.adjust) ) ) + 
  geom_point() + 
  scale_color_gradient(low = "blue" , high = "red"  , breaks = c(1,10,20,30,40,50,60) , limits = c(1,60) ) + 
  theme_bw() + 
  theme( axis.text.x = element_text(colour="black",size=11), axis.text.y = element_text(colour="black",size=8, hjust = 0.5 ) )
gg_clusterCompare_center

Heatmap of DNA damage response genes

Load the list of DNA damage response genes.

dna_damage_genes <- read.csv("gene_lists/DNA_damage_genes.csv", stringsAsFactors = FALSE )
#readxl::read_xlsx(path = "gene_lists/dna damage genes for Sheng.xlsx" , col_names = TRUE ) %>%  dplyr::filter( ! is.na(ensembl_gene_id) & gene_symbol != "TREX2")

Convert the Module column to factor.

dna_damage_genes$module <- as.factor(dna_damage_genes$module)
dna_damage_genes

Get the TPM gene expression values for these genes from the TPM table

TPM_dna_damage_genes <- TPM_NSCs %>% dplyr::filter( ensembl_gene_id %in% dna_damage_genes$ensembl_gene_id  )

Combine the two data.frames

TPM_combined <- left_join(x = dna_damage_genes , y = TPM_dna_damage_genes , by = "ensembl_gene_id" )
Column `ensembl_gene_id` joining character vector and factor, coercing into character vector
head(TPM_combined)
cell_order <- pseudotime_ordering %>% mutate( typesort = as.character(fct_recode(.f = type , c = "a1" , d = "a2" , a = "q1" , b = "q2") ) ) %>% group_by(age) %>% arrange(age, typesort) %>% pull(cell) %>% as.character()
library(pheatmap)

TPM_mat <- as.matrix(TPM_combined %>% dplyr::select( c( "ensembl_gene_id" , cell_order ) ) %>% column_to_rownames("ensembl_gene_id"))

TPM_mat_names <- as.matrix(TPM_combined %>% dplyr::select( c( "gene_symbol" , cell_order ) ) %>% column_to_rownames("gene_symbol"))

anno_row <- dplyr::select(dna_damage_genes , module , ensembl_gene_id ) %>% column_to_rownames("ensembl_gene_id")


anno_col <- NSCs_annotation %>% dplyr::select(-cell)

Plot log transformed TPM values

pheatmap(
  mat = pmin( log( TPM_mat + 1 ) , 7 ) , 
  cluster_rows = FALSE , 
  cluster_cols = FALSE , 
  scale = "none" , 
  breaks = seq(0,7,length.out = 101) , 
  color = viridisLite::viridis(n = 100) , 
  border_color = NA , 
  # gaps_row = row_breaks[seq_len(length.out = length(row_breaks) - 1 )] ,
  annotation_col = anno_col , 
  annotation_colors = list(
      type = c(q1 = "steelblue" , q2 = "steelblue1" , a1 = "tomato" , a2 = "sienna1"), 
      age = c( young = "yellowgreen" , old = "slateblue")
    )
)

Determine gaps between categories

row_breaks <- cumsum( anno_row %>% group_by(module) %>% mutate( num = length(module)) %>% unique() %>% pull(num) ) 

Plot log transformed TPM values with gene names as rownames

anno_col_rename <- anno_col

anno_col_rename$type <- as.character(anno_col_rename$type)

anno_col_rename$type[anno_col_rename$type == "q1"] <- "qNSC1"
anno_col_rename$type[anno_col_rename$type == "q2"] <- "qNSC2"
anno_col_rename$type[anno_col_rename$type == "a1"] <- "aNSC1"
anno_col_rename$type[anno_col_rename$type == "a2"] <- "aNSC2"

anno_col_rename$type <- factor(x = anno_col_rename$type , levels = c("qNSC1","qNSC2","aNSC1","aNSC2") ) 
# scale_white_red <- colorRampPalette(colors = RColorBrewer::brewer.pal(n = 9 , name = "Reds")  )
scale_white_red <- colorRampPalette(colors = c("white","red"))
pheatmap(
  mat = pmin( log( TPM_mat_names + 1 ) , 8 ) , 
  cluster_rows = FALSE , 
  cluster_cols = FALSE , 
  scale = "none" , 
  breaks = seq(0,8,length.out = 101) , 
  color = scale_white_red(n = 100) , 
  annotation_col = anno_col_rename , 
  annotation_colors = list(
      type = c(qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1"), 
      age = c( young = "yellowgreen" , old = "slateblue")
    ),
  gaps_col = 133,
  show_colnames = FALSE, 
  fontsize_row = 7
)

Differentially expressed genes between old and young

DESeq2

library(DESeq2)
Loading required package: GenomicRanges
Loading required package: GenomeInfoDb
Loading required package: SummarizedExperiment
Loading required package: DelayedArray
Loading required package: matrixStats

Attaching package: ‘matrixStats’

The following object is masked from ‘package:dplyr’:

    count

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians


Attaching package: ‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following object is masked from ‘package:base’:

    apply
library(tibble)
library(BiocParallel)

Register number of cores for parallel execution

register(BPPARAM =  MulticoreParam(workers = 4) , default = TRUE)

Load the raw counts for all the cells

countData <- read.csv(file = "count_table/raw_counts_NSCs_SMARTseq2.csv" , header = TRUE , row.names = 1)

And we load the cell annotation.

colData <- NSCs_annotation
colData$type_save <- colData$type
levels(colData$type) <- c("aNSC1","aNSC2","qNSC1","qNSC2")
comparisons <- list( aNSC = c("aNSC1","aNSC2") , qNSC = c("qNSC1","qNSC2") , NSC = c("qNSC1","qNSC2","aNSC1","aNSC2") , qNSC1 = c("qNSC1") ,qNSC2 = c("qNSC2"), aNSC1 = c("aNSC1"), aNSC2 = c("aNSC2") )

Now we want to see if all our cells available in the colData are also found in the countData table?

all(colData$cell %in% colnames(countData))
[1] TRUE

And if their order is the same?

all(colData$cell == colnames(countData)[-1])
[1] TRUE

Great, thus we can proceed and set up our DESeq2 objects in a list.

The comparisons we are interested in are:

  • aNSC: old vs young
  • qNSC: old vs young
  • all NSCs: old vs young
  • individual celltypes: old vs young

Rename the gene column

countData <- dplyr::rename( countData ,  gene = ensembl_gene_id )

Subset the data from colData and countData according to the celltypes into a list

celltype_data_list <- lapply(
  
  X =  comparisons , 
  
  FUN = function(x){
    colD <- dplyr::filter( colData ,  type %in% x )
    
    cell_ids <- colD$cell
    
    countD <- dplyr::select( countData , one_of( "gene" , as.character(cell_ids)  ))
    
    list( colData = colD , countData = countD )
  }
)

Check the order of the celltypes in the list

celltype_order <- lapply(
  X = celltype_data_list , 
  FUN = function(x){ as.character( unique( x$colData$type ) ) }
)
celltype_order
$aNSC
[1] "aNSC1" "aNSC2"

$qNSC
[1] "qNSC1" "qNSC2"

$NSC
[1] "aNSC1" "aNSC2" "qNSC1" "qNSC2"

$qNSC1
[1] "qNSC1"

$qNSC2
[1] "qNSC2"

$aNSC1
[1] "aNSC1"

$aNSC2
[1] "aNSC2"

Prepare DESeq objects

Make a list of DESeqDataSets - one for each celltype Only keep expressed genes in the data sets Set "young" as base level for comparison: Thus a FC > 0 will mean it is higher in the old cells

Because we have expected reads from the RSEM output, we need to round the values to integer, as DESeq2 expects integer values

celltype_data_list <- lapply(
  
  X = celltype_data_list , 
  
  FUN = function(x){
    rownames(x$countData) <- NULL
    rownames(x$colData) <- NULL
    
    dds <- DESeqDataSetFromMatrix(countData = round(column_to_rownames( df = x$countData , var = "gene")),
                              colData = column_to_rownames( df = x$colData , var = "cell" ),
                              design = ~ age )
    
    dds <- dds[ rowSums(counts(dds)) > 1, ]
    dds$age <- relevel(x = dds$age , ref = "young")
    
    dds
  }
)

Run DESeq

Run DESeq on the list of dds objects - will be parallely run on the number of cores set in the start of this file by register() ...

loopnum = 0

celltype_data_list <- lapply(
  
  X = celltype_data_list , 
  
  FUN = function(dds){
    
    loopnum <<- loopnum + 1 
    
    print(paste("Running DESeq for field:", loopnum ) )
    
    DESeq(object = dds , parallel = TRUE )
  
  }
)

Extract the results from the DESeq2 data sets

loopnum = 0

results_list <- lapply(
  
  X = celltype_data_list , 
  
  FUN = function(dds){

    loopnum <<- loopnum + 1 
    
    print(paste("Extract results for field:", loopnum ) )

    DESeq2::results(object = dds , tidy = TRUE , parallel = TRUE )  
  
  }
)

Save the DESeq2 data sets list and the results list as RDS files

saveRDS(object = results_list , file = "results/DE_DESeq2_old_vs_young/results_list.RDS")
saveRDS(object = celltype_data_list , file = "results/DE_DESeq2_old_vs_young/DESeq2_celltype_data_list.RDS")

Extract the individual DE tables from the list and save them individually as csv files

write.csv( x = results_list[[1]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[1]] , ".csv" ) )
write.csv( x = results_list[[2]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[2]] , ".csv"   ) )
write.csv( x = results_list[[3]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[3]] , ".csv"   ) )
write.csv( x = results_list[[4]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[4]] , ".csv"   ) )
write.csv( x = results_list[[5]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[5]] , ".csv"   ) )
write.csv( x = results_list[[6]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[6]] , ".csv"   ) )
write.csv( x = results_list[[7]] , file = paste0("results/DE_DESeq2_old_vs_young/" , "DESeq2_result_" , names(comparisons)[[7]] , ".csv"   ) )

t-Test

NSCs

# Load the TPM expression values for the SMARTseq2 data
TPM_NSC <- remove_rownames(df = TPM_NSCs) %>% column_to_rownames(var = "ensembl_gene_id" )
# Load the cell annotation
NSC_anno <- NSCs_annotation
# Subset the expression matrix for young and old into different matrices
TPM_old <- TPM_NSC[as.character(NSC_anno[NSC_anno$age == "old",]$cell)]
TPM_young <- TPM_NSC[as.character(NSC_anno[NSC_anno$age == "young",]$cell)]
# Log transform the expression values 
TPM_old <- log(TPM_old+1)
TPM_young <- log(TPM_young+1)
TPM_NSC <- as.matrix( log(TPM_NSC+1) )
# ------------------------------------------------------------------------------------------------------------
# Calculate the mean expression, standard deviation and number of cells with 0 counts for each row (gene) for young and old cells separately
table_sms2 <- data.frame( 
  ensembl_gene_id = rownames(TPM_young),
  avg_logTPM_young = apply(TPM_young , MARGIN = 1 , FUN = mean)  , 
  avg_logTPM_old = apply(TPM_old , MARGIN = 1 , FUN = mean)  ,
  avg_logTPM = apply(TPM_NSC , MARGIN = 1 , FUN = mean) ,
  sd_logTPM_young = apply(TPM_young , MARGIN = 1 , FUN = sd)  ,
  sd_logTPM_old = apply(TPM_old , MARGIN = 1 , FUN = sd),
  fraction_cells_zero_young = apply(TPM_young == 0 , MARGIN = 1 , FUN = sum)/length(TPM_young),
  fraction_cells_zero_old = apply(TPM_old == 0 , MARGIN = 1 , FUN = sum)/length(TPM_old)
)
# Calculate the difference between the mean from old and young (old - young)
table_sms2$difference_of_avg <- (table_sms2$avg_logTPM_old - table_sms2$avg_logTPM_young )
# Calculate the mean Standard Deviation between young and old
table_sms2$mean_sd <- apply( X =  table_sms2[,c("sd_logTPM_young","sd_logTPM_old")] , MARGIN = 1 , FUN = mean)
# Finally calculate Cohens D, by deviding the difference of the mean values by the mean standard deviation 
table_sms2$'difference_of_avg/mean_sd'  <- table_sms2$difference_of_avg/table_sms2$mean_sd
# ------------------------------------------------------------------------------------------------------------
# Add p-values from t-test
# Run t-test on SMARTseq2 NSC data old and young
library(genefilter)
# Prepare factor with young and old in order of the column names
fact <- as.character( colnames(TPM_NSC) )
fact[ grepl(x = fact , pattern = "s_dot") ] <- "old"
fact[ grepl(x = fact , pattern = "^N" ) ] <- "young"
fact <- factor( fact )
# Prepare matrix for t-test input
TPM_NSC_mat <- TPM_NSC
TPM_NSC_mat <- as.matrix( TPM_NSC_mat ) 
# Run t-test with rowttests function from genefilter packages
t_test_NSCs_SMARTseq2 <- rowttests(x = TPM_NSC_mat , fac = fact )
# Add ensembl_gene_id as column from the rownames
t_test_NSCs_SMARTseq2$ensembl_gene_id <- rownames(t_test_NSCs_SMARTseq2) 
# Join the tables
table_sms2_merged_with_ttest <- full_join(x = table_sms2 , y = t_test_NSCs_SMARTseq2 , by = "ensembl_gene_id" )
Column `ensembl_gene_id` joining factor and character vector, coercing into character vector
table_sms2_merged_with_ttest <- arrange(table_sms2_merged_with_ttest , desc(difference_of_avg/mean_sd))
## Save the results as a csv file
# write.csv(x = table_sms2_merged_with_ttest , file = "DE_results/DE_NSC_SmartSeq2/DE_NSCs_SmartSeq2_t-test_CohensD.csv" )

Expression of differentially expressed genes from Bulk NSCs

# Load bulk NSCs DE genes between old and young animals
bulk_DE_results <- read.csv("../Bulk_sequencing/DESeq2_results_old_vs_young/GP_DESeq2_results_Old_vs_Yang.csv" , row.names = 1)
# Merge the table of calculated values with the DESeq2 output of the bulk NSC comparison old vs young by ensembl_gene_id
tables_sms2_merged <- full_join(x = table_sms2 , y = bulk_DE_results)
Joining, by = "ensembl_gene_id"
Column `ensembl_gene_id` joining factors with different levels, coercing to character vector
# ------------------------------------------------------------------------------------------------------------
# Plot the difference in mean expression versus the parallel maximum of zero-count cell percentage
tables_sms2_merged %>% 
  filter(padj < 0.05) %>%
  ggplot( aes(
    x = pmax( fraction_cells_zero_old , fraction_cells_zero_young )  , 
    y = avg_logTPM_old - avg_logTPM_young , 
    color = factor(sign(log2FoldChange))
    )) + geom_point()

# Same plot with blue (up) and red (down) colored points and axes labels
library(ggrepel)
library(cowplot)
as_tibble(tables_sms2_merged) %>%
    filter( padj < 0.05) %>%
    mutate( col = case_when(
      padj > 0.05 ~ "n.s." , 
      log2FoldChange > 0.3 ~ "up",
      log2FoldChange < -0.3 ~ "down",
      TRUE ~ "n.s." ) ) %>% 
    ggplot( aes(
      x = pmax( fraction_cells_zero_old , fraction_cells_zero_young )  , 
      y = avg_logTPM_old - avg_logTPM_young , 
      color = col 
    )) + 
    geom_point() +
    geom_point(size = 1) +
    geom_hline(yintercept = 0 , color = "grey40") +
    xlab("Max. percentage of cells with no reads per gene in old or young") +
    ylab("Difference of avg. log(TPM+1) \n between old and young") +
    theme_cowplot() + theme(panel.grid.major = element_line(colour = "grey80")) +
    scale_color_manual( name = "Direction of change in bulk" , values = c(down = "red" , up = "blue")) 

    
# --> exported to PDF 6x9 inches and 4x9 (wide)

individual subpopulations

# Load the TPM expression values for the SMARTseq2 data
TPM_NSC <- remove_rownames(df = TPM_NSCs) %>% column_to_rownames( var = "ensembl_gene_id" )
# Load the cell annotation
NSC_anno <- NSCs_annotation 
NSC_anno$type <- recode_factor( NSC_anno$type , q1 = "qNSC1", q2 = "qNSC2", a1 = "aNSC1" , a2 = "aNSC2" )
# Subset the expression matrix for young and old into different matrices
TPM_old <- TPM_NSC[as.character(NSC_anno[NSC_anno$age == "old",]$cell)]
TPM_young <- TPM_NSC[as.character(NSC_anno[NSC_anno$age == "young",]$cell)]
# Log transform the expression values 
TPM_old <- log(TPM_old+1)
TPM_young <- log(TPM_young+1)
TPM_NSC <- as.matrix( log(TPM_NSC+1) )
NSC_anno_young <- NSC_anno[NSC_anno$age == "young",]
NSC_anno_old <- NSC_anno[NSC_anno$age == "old",]
# ------------------------------------------------------------------------------------------------------------
# Function that perform calculation of 
run_ttest_and_calculate_Cohens_d <- function(subpop){
    ## Subset cells for individual subpopulations
    TPM_young_subpop <- TPM_young[as.character(NSC_anno_young[NSC_anno_young$type == subpop,]$cell)]
    TPM_old_subpop <- TPM_old[as.character(NSC_anno_old[NSC_anno_old$type == subpop,]$cell)]
    TPM_NSC_subpop <- TPM_NSC[,as.character(NSC_anno[NSC_anno$type == subpop,]$cell)]
  
    # Calculate the mean expression, standard deviation and number of cells with 0 counts for each row (gene) for young and old cells separately
    table_sms2 <- data.frame( 
      ensembl_gene_id = rownames(TPM_young_subpop),
      avg_logTPM_young = apply(TPM_young_subpop , MARGIN = 1 , FUN = mean)  , 
      avg_logTPM_old = apply(TPM_old_subpop , MARGIN = 1 , FUN = mean)  ,
      sd_logTPM_young = apply(TPM_young_subpop , MARGIN = 1 , FUN = sd)  ,
      sd_logTPM_old = apply(TPM_old_subpop , MARGIN = 1 , FUN = sd),
      fraction_cells_zero_young = apply(TPM_young_subpop == 0 , MARGIN = 1 , FUN = sum)/length(TPM_young_subpop),
      fraction_cells_zero_old = apply(TPM_old_subpop == 0 , MARGIN = 1 , FUN = sum)/length(TPM_old_subpop)
    )
    
    # Calculate the difference between the mean from old and young (old - young)
    table_sms2$difference_of_avg <- (table_sms2$avg_logTPM_old - table_sms2$avg_logTPM_young )
    
    # Calculate the mean Standard Deviation between young and old
    table_sms2$mean_sd <- apply( X =  table_sms2[,c("sd_logTPM_young","sd_logTPM_old")] , MARGIN = 1 , FUN = mean)
    
    # Finally calculate Cohens D, by deviding the difference of the mean values by the mean standard deviation 
    table_sms2$'difference_of_avg/mean_sd' <- table_sms2$difference_of_avg/table_sms2$mean_sd
    
    # ------------------------------------------------------------------------------------------------------------
    # Add p-values from t-test
    
    # Run t-test on SMARTseq2 NSC data old and young
    
    # Prepare factor with young and old in order of the column names
    fact <- as.character( colnames(TPM_NSC_subpop) )
    fact[ grepl(x = fact , pattern = "s_dot") ] <- "old"
    fact[ grepl(x = fact , pattern = "^N" ) ] <- "young"
    fact <- factor( fact )
    
    # Prepare matrix for t-test input
    TPM_NSC_mat <- TPM_NSC_subpop
    TPM_NSC_mat <- as.matrix( TPM_NSC_mat ) 
    
    # Run t-test with rowttests function from genefilter packages
    t_test_NSCs_SMARTseq2 <- rowttests(x = TPM_NSC_mat , fac = fact )
    
    # Add ensembl_gene_id as column from the rownames
    t_test_NSCs_SMARTseq2$ensembl_gene_id <- rownames(t_test_NSCs_SMARTseq2) 
    
    # Join the tables
    table_sms2_merged_with_ttest <- full_join(x = table_sms2 , y = t_test_NSCs_SMARTseq2 , by = "ensembl_gene_id" )
    table_sms2_merged_with_ttest
}
# ------------------------------------------------------------------------------------------------------------
# Run the t-test for all subpopulations individually
subpopulations <- list(qNSC1 = "qNSC1", qNSC2 = "qNSC2", aNSC1 = "aNSC1", aNSC2 = "aNSC2")
ttest_results_cohensd <- lapply(X = subpopulations , FUN = run_ttest_and_calculate_Cohens_d ) 
Column `ensembl_gene_id` joining factor and character vector, coercing into character vectorColumn `ensembl_gene_id` joining factor and character vector, coercing into character vectorColumn `ensembl_gene_id` joining factor and character vector, coercing into character vectorColumn `ensembl_gene_id` joining factor and character vector, coercing into character vector
# Order the table by cohens d
ttest_results_cohensd <- lapply(ttest_results_cohensd, FUN = function(x){arrange(x, desc(difference_of_avg/mean_sd))} )
## Save the results as a csv file
# write.csv(x = ttest_results_cohensd[[1]] , file = paste0("DE_results/DE_NSC_SmartSeq2/subpopulations/DE_SmartSeq2_t-test_CohensD_",subpopulations[[1]],".csv") )
# write.csv(x = ttest_results_cohensd[[2]] , file = paste0("DE_results/DE_NSC_SmartSeq2/subpopulations/DE_SmartSeq2_t-test_CohensD_",subpopulations[[2]],".csv") )
# write.csv(x = ttest_results_cohensd[[3]] , file = paste0("DE_results/DE_NSC_SmartSeq2/subpopulations/DE_SmartSeq2_t-test_CohensD_",subpopulations[[3]],".csv") )
# write.csv(x = ttest_results_cohensd[[4]] , file = paste0("DE_results/DE_NSC_SmartSeq2/subpopulations/DE_SmartSeq2_t-test_CohensD_",subpopulations[[4]],".csv") )

Difference of the mean Expression vs. Mean SD Plots

qNSC1 vs. qNSC2
## t-test between qNSC1 and qNSC2 SMARTseq2
## Subset cells for individual subpopulations
TPM_NSC_qNSC1 <- TPM_NSC[,as.character(NSC_anno[NSC_anno$type == "qNSC1",]$cell)]
TPM_NSC_qNSC2 <- TPM_NSC[,as.character(NSC_anno[NSC_anno$type == "qNSC2",]$cell)]
TPM_NSC_aNSC1 <- TPM_NSC[,as.character(NSC_anno[NSC_anno$type == "aNSC1",]$cell)]
TPM_NSC_aNSC2 <- TPM_NSC[,as.character(NSC_anno[NSC_anno$type == "aNSC2",]$cell)]
TPM_NSC_qNSC1_qNSC2 <- as.matrix( cbind( TPM_NSC_qNSC1 , TPM_NSC_qNSC2 ) ) 
q1q2 <- c( rep( "qNSC1" , 134 ) , rep( "qNSC2" , 40 ) )
t_test_qNSC1_vs_2_SMARTseq2 <- rowttests(x = as.matrix( TPM_NSC_qNSC1_qNSC2 ) , fac = factor( q1q2 ) )
tab <- data.frame(
  ensembl_gene_id = rownames(TPM_NSC_qNSC1),
  mean_qNSC1 = rowMeans( TPM_NSC_qNSC1 ) ,
  mean_qNSC2 = rowMeans( TPM_NSC_qNSC2 ) , 
  var_qNSC1 = apply(X = TPM_NSC_qNSC1 , MARGIN = 1 , FUN = var ),
  var_qNSC2 = apply(X = TPM_NSC_qNSC2 , MARGIN = 1 , FUN = var ),
  sd_qNSC1 = apply(X = TPM_NSC_qNSC1 , MARGIN = 1 , FUN = sd ),
  sd_qNSC2 = apply(X = TPM_NSC_qNSC2 , MARGIN = 1 , FUN = sd )
)
tab$mean_var <- apply(X = tab[,c("var_qNSC1","var_qNSC2")] , MARGIN = 1 , FUN = mean )
tab$mean_sd <- apply(X = tab[,c("sd_qNSC1","sd_qNSC2")] , MARGIN = 1 , FUN = mean )
tab$difference_of_avg <- (tab$mean_qNSC1 - tab$mean_qNSC2 )
tab$'difference_of_avg/mean_sd' <- tab$difference_of_avg/tab$mean_sd
# Add ensembl_gene_id as column from the rownames
t_test_qNSC1_vs_2_SMARTseq2$ensembl_gene_id <- rownames(t_test_qNSC1_vs_2_SMARTseq2) 
# Join the tables
t_test_qNSC1_vs_2_SMARTseq2_merged_with_ttest <- full_join(x = tab , y = t_test_qNSC1_vs_2_SMARTseq2 , by = "ensembl_gene_id" )
Column `ensembl_gene_id` joining factor and character vector, coercing into character vector
library(cowplot)
ggplot(data = t_test_qNSC1_vs_2_SMARTseq2_merged_with_ttest , aes(y = mean_sd , x = mean_qNSC1 - mean_qNSC2 , color = abs(difference_of_avg/mean_sd) > 0.8 )) + geom_point( alpha = 0.5 , size = 1    ) + ggtitle("Comparison: qNSC1 vs qNSC2") + xlim(c(-5,5)) + theme_cowplot() + theme(panel.grid.major = element_line(colour = "grey80")) + xlab("Difference of mean expressions") + ylab("Average SD")

ggplot(data = tab , aes(y = mean_sd , x = mean_qNSC1 - mean_qNSC2 )) + geom_point( alpha = 0.1 , size = 1 ) + ggtitle("Comparison: qNSC1 vs qNSC2") + xlim(c(-5,5)) + theme_cowplot() + theme(panel.grid.major = element_line(colour = "grey80")) + xlab("Difference of mean expressions") + ylab("Average SD")

qNSC1: old vs. young
tab_q1_old_young <- run_ttest_and_calculate_Cohens_d(subpop = "qNSC1" )
Column `ensembl_gene_id` joining factor and character vector, coercing into character vector
ggplot(data = tab_q1_old_young , aes(y = mean_sd , x = difference_of_avg , color = abs(difference_of_avg/mean_sd) > 0.8  )) + geom_point( alpha = 0.5 , size = 1 ) + ggtitle("Comparison: qNSC1 - old vs young") + xlim(c(-5,5)) + theme_cowplot() + theme(panel.grid.major = element_line(colour = "grey80"))  + xlab("Difference of mean expressions") + ylab("Average SD") 

ggplot(data = tab_q1_old_young , aes(y = mean_sd , x = difference_of_avg )) + geom_point( alpha = 0.1 , size = 1 ) + ggtitle("Comparison: qNSC1 - old vs young") + xlim(c(-5,5)) + theme_cowplot() + theme(panel.grid.major = element_line(colour = "grey80"))  + xlab("Difference of mean expressions") + ylab("Average SD") 

Euclidean Distances (work on it)

Load the TPM values

smartseq2_data <- read.csv(file = "count_table/TPM_NSC_and_Astro/old_young_combined/Gene_expression_matrix_TPM_all.csv" , row.names = 1)
smartseq2_data <- smartseq2_data %>% remove_rownames() %>% column_to_rownames("gene_id")

Also we load the annotation

smartseq2_annotation <- read.csv(file = "count_table/cell_annotation_NSC_Astro/old_young_combined/cell_annotation.csv" , row.names = 1)

Which celltypes do we have?

celltypes <- unique(as.character(smartseq2_annotation$type))
celltypes
[1] "Astro" "aNSC1" "aNSC2" "qNSC1" "qNSC2"

Create Seurat object

seurat_sms2 <- CreateSeuratObject(raw.data = smartseq2_data , min.cells = 3, project = "young_vs_old_SmartSeq2")
seurat_sms2 <- AddMetaData(object = seurat_sms2, metadata = smartseq2_annotation %>% remove_rownames() %>% column_to_rownames("cell") )
seurat_sms2 <- NormalizeData(object = seurat_sms2, normalization.method = "LogNormalize" )
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
seurat_sms2 <- ScaleData(object = seurat_sms2, vars.to.regress = c("nUMI", "nGene"))
[1] "Regressing out nUMI"  "Regressing out nGene"

  |                                                                                                                           
  |                                                                                                                     |   0%
  |                                                                                                                           
  |=                                                                                                                    |   1%
  |                                                                                                                           
  |==                                                                                                                   |   2%
  |                                                                                                                           
  |===                                                                                                                  |   3%
  |                                                                                                                           
  |====                                                                                                                 |   3%
  |                                                                                                                           
  |====                                                                                                                 |   4%
  |                                                                                                                           
  |=====                                                                                                                |   4%
  |                                                                                                                           
  |=====                                                                                                                |   5%
  |                                                                                                                           
  |======                                                                                                               |   5%
  |                                                                                                                           
  |=======                                                                                                              |   6%
  |                                                                                                                           
  |========                                                                                                             |   7%
  |                                                                                                                           
  |=========                                                                                                            |   8%
  |                                                                                                                           
  |==========                                                                                                           |   8%
  |                                                                                                                           
  |==========                                                                                                           |   9%
  |                                                                                                                           
  |===========                                                                                                          |   9%
  |                                                                                                                           
  |===========                                                                                                          |  10%
  |                                                                                                                           
  |============                                                                                                         |  10%
  |                                                                                                                           
  |=============                                                                                                        |  11%
  |                                                                                                                           
  |==============                                                                                                       |  12%
  |                                                                                                                           
  |===============                                                                                                      |  13%
  |                                                                                                                           
  |================                                                                                                     |  13%
  |                                                                                                                           
  |================                                                                                                     |  14%
  |                                                                                                                           
  |=================                                                                                                    |  14%
  |                                                                                                                           
  |=================                                                                                                    |  15%
  |                                                                                                                           
  |==================                                                                                                   |  15%
  |                                                                                                                           
  |===================                                                                                                  |  16%
  |                                                                                                                           
  |====================                                                                                                 |  17%
  |                                                                                                                           
  |=====================                                                                                                |  18%
  |                                                                                                                           
  |======================                                                                                               |  18%
  |                                                                                                                           
  |======================                                                                                               |  19%
  |                                                                                                                           
  |=======================                                                                                              |  19%
  |                                                                                                                           
  |=======================                                                                                              |  20%
  |                                                                                                                           
  |========================                                                                                             |  21%
  |                                                                                                                           
  |=========================                                                                                            |  21%
  |                                                                                                                           
  |=========================                                                                                            |  22%
  |                                                                                                                           
  |==========================                                                                                           |  22%
  |                                                                                                                           
  |==========================                                                                                           |  23%
  |                                                                                                                           
  |===========================                                                                                          |  23%
  |                                                                                                                           
  |============================                                                                                         |  24%
  |                                                                                                                           
  |=============================                                                                                        |  25%
  |                                                                                                                           
  |==============================                                                                                       |  26%
  |                                                                                                                           
  |===============================                                                                                      |  26%
  |                                                                                                                           
  |===============================                                                                                      |  27%
  |                                                                                                                           
  |================================                                                                                     |  27%
  |                                                                                                                           
  |================================                                                                                     |  28%
  |                                                                                                                           
  |=================================                                                                                    |  28%
  |                                                                                                                           
  |==================================                                                                                   |  29%
  |                                                                                                                           
  |===================================                                                                                  |  30%
  |                                                                                                                           
  |====================================                                                                                 |  31%
  |                                                                                                                           
  |=====================================                                                                                |  31%
  |                                                                                                                           
  |=====================================                                                                                |  32%
  |                                                                                                                           
  |======================================                                                                               |  32%
  |                                                                                                                           
  |======================================                                                                               |  33%
  |                                                                                                                           
  |=======================================                                                                              |  33%
  |                                                                                                                           
  |========================================                                                                             |  34%
  |                                                                                                                           
  |=========================================                                                                            |  35%
  |                                                                                                                           
  |==========================================                                                                           |  36%
  |                                                                                                                           
  |===========================================                                                                          |  36%
  |                                                                                                                           
  |===========================================                                                                          |  37%
  |                                                                                                                           
  |============================================                                                                         |  37%
  |                                                                                                                           
  |============================================                                                                         |  38%
  |                                                                                                                           
  |=============================================                                                                        |  38%
  |                                                                                                                           
  |==============================================                                                                       |  39%
  |                                                                                                                           
  |===============================================                                                                      |  40%
  |                                                                                                                           
  |===============================================                                                                      |  41%
  |                                                                                                                           
  |================================================                                                                     |  41%
  |                                                                                                                           
  |=================================================                                                                    |  42%
  |                                                                                                                           
  |==================================================                                                                   |  43%
  |                                                                                                                           
  |===================================================                                                                  |  44%
  |                                                                                                                           
  |====================================================                                                                 |  44%
  |                                                                                                                           
  |====================================================                                                                 |  45%
  |                                                                                                                           
  |=====================================================                                                                |  45%
  |                                                                                                                           
  |=====================================================                                                                |  46%
  |                                                                                                                           
  |======================================================                                                               |  46%
  |                                                                                                                           
  |=======================================================                                                              |  47%
  |                                                                                                                           
  |========================================================                                                             |  48%
  |                                                                                                                           
  |=========================================================                                                            |  49%
  |                                                                                                                           
  |==========================================================                                                           |  49%
  |                                                                                                                           
  |==========================================================                                                           |  50%
  |                                                                                                                           
  |===========================================================                                                          |  50%
  |                                                                                                                           
  |===========================================================                                                          |  51%
  |                                                                                                                           
  |============================================================                                                         |  51%
  |                                                                                                                           
  |=============================================================                                                        |  52%
  |                                                                                                                           
  |==============================================================                                                       |  53%
  |                                                                                                                           
  |===============================================================                                                      |  54%
  |                                                                                                                           
  |================================================================                                                     |  54%
  |                                                                                                                           
  |================================================================                                                     |  55%
  |                                                                                                                           
  |=================================================================                                                    |  55%
  |                                                                                                                           
  |=================================================================                                                    |  56%
  |                                                                                                                           
  |==================================================================                                                   |  56%
  |                                                                                                                           
  |===================================================================                                                  |  57%
  |                                                                                                                           
  |====================================================================                                                 |  58%
  |                                                                                                                           
  |=====================================================================                                                |  59%
  |                                                                                                                           
  |======================================================================                                               |  59%
  |                                                                                                                           
  |======================================================================                                               |  60%
  |                                                                                                                           
  |=======================================================================                                              |  61%
  |                                                                                                                           
  |========================================================================                                             |  62%
  |                                                                                                                           
  |=========================================================================                                            |  62%
  |                                                                                                                           
  |=========================================================================                                            |  63%
  |                                                                                                                           
  |==========================================================================                                           |  63%
  |                                                                                                                           
  |==========================================================================                                           |  64%
  |                                                                                                                           
  |===========================================================================                                          |  64%
  |                                                                                                                           
  |============================================================================                                         |  65%
  |                                                                                                                           
  |=============================================================================                                        |  66%
  |                                                                                                                           
  |==============================================================================                                       |  67%
  |                                                                                                                           
  |===============================================================================                                      |  67%
  |                                                                                                                           
  |===============================================================================                                      |  68%
  |                                                                                                                           
  |================================================================================                                     |  68%
  |                                                                                                                           
  |================================================================================                                     |  69%
  |                                                                                                                           
  |=================================================================================                                    |  69%
  |                                                                                                                           
  |==================================================================================                                   |  70%
  |                                                                                                                           
  |===================================================================================                                  |  71%
  |                                                                                                                           
  |====================================================================================                                 |  72%
  |                                                                                                                           
  |=====================================================================================                                |  72%
  |                                                                                                                           
  |=====================================================================================                                |  73%
  |                                                                                                                           
  |======================================================================================                               |  73%
  |                                                                                                                           
  |======================================================================================                               |  74%
  |                                                                                                                           
  |=======================================================================================                              |  74%
  |                                                                                                                           
  |========================================================================================                             |  75%
  |                                                                                                                           
  |=========================================================================================                            |  76%
  |                                                                                                                           
  |==========================================================================================                           |  77%
  |                                                                                                                           
  |===========================================================================================                          |  77%
  |                                                                                                                           
  |===========================================================================================                          |  78%
  |                                                                                                                           
  |============================================================================================                         |  78%
  |                                                                                                                           
  |============================================================================================                         |  79%
  |                                                                                                                           
  |=============================================================================================                        |  79%
  |                                                                                                                           
  |==============================================================================================                       |  80%
  |                                                                                                                           
  |==============================================================================================                       |  81%
  |                                                                                                                           
  |===============================================================================================                      |  81%
  |                                                                                                                           
  |===============================================================================================                      |  82%
  |                                                                                                                           
  |================================================================================================                     |  82%
  |                                                                                                                           
  |=================================================================================================                    |  83%
  |                                                                                                                           
  |==================================================================================================                   |  84%
  |                                                                                                                           
  |===================================================================================================                  |  85%
  |                                                                                                                           
  |====================================================================================================                 |  85%
  |                                                                                                                           
  |====================================================================================================                 |  86%
  |                                                                                                                           
  |=====================================================================================================                |  86%
  |                                                                                                                           
  |=====================================================================================================                |  87%
  |                                                                                                                           
  |======================================================================================================               |  87%
  |                                                                                                                           
  |=======================================================================================================              |  88%
  |                                                                                                                           
  |========================================================================================================             |  89%
  |                                                                                                                           
  |=========================================================================================================            |  90%
  |                                                                                                                           
  |==========================================================================================================           |  90%
  |                                                                                                                           
  |==========================================================================================================           |  91%
  |                                                                                                                           
  |===========================================================================================================          |  91%
  |                                                                                                                           
  |===========================================================================================================          |  92%
  |                                                                                                                           
  |============================================================================================================         |  92%
  |                                                                                                                           
  |=============================================================================================================        |  93%
  |                                                                                                                           
  |==============================================================================================================       |  94%
  |                                                                                                                           
  |===============================================================================================================      |  95%
  |                                                                                                                           
  |================================================================================================================     |  95%
  |                                                                                                                           
  |================================================================================================================     |  96%
  |                                                                                                                           
  |=================================================================================================================    |  96%
  |                                                                                                                           
  |=================================================================================================================    |  97%
  |                                                                                                                           
  |==================================================================================================================   |  97%
  |                                                                                                                           
  |===================================================================================================================  |  98%
  |                                                                                                                           
  |==================================================================================================================== |  99%
  |                                                                                                                           
  |=====================================================================================================================| 100%
[1] "Scaling data matrix"

  |                                                                                                                           
  |                                                                                                                     |   0%
  |                                                                                                                           
  |=====================================================================================================================| 100%
seurat_sms2 <- FindVariableGenes(object = seurat_sms2, mean.function = ExpMean, dispersion.function = LogVMR, y.cutoff = 0.75)
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
**************************************************|

genes.var <- apply(X = seurat_sms2@raw.data , MARGIN = 1 , FUN = var)
genes.var.top <- names( sort(genes.var , decreasing = TRUE)[1:2000] )
seurat_sms2@var.genes <- genes.var.top
seurat_sms2@imputed <- as.data.frame.matrix(seurat_sms2@data)
seurat_sms2 <- RunPCA(object = seurat_sms2, pc.genes = seurat_sms2@var.genes, do.print = TRUE, pcs.print = 1:5, genes.print = 5 , use.imputed = TRUE )
[1] "PC1"
[1] "ENSMUSG00000047945" "ENSMUSG00000020737" "ENSMUSG00000049775" "ENSMUSG00000001525" "ENSMUSG00000003038"
[1] ""
[1] "ENSMUSG00000028517" "ENSMUSG00000022037" "ENSMUSG00000006205" "ENSMUSG00000002985" "ENSMUSG00000041329"
[1] ""
[1] ""
[1] "PC2"
[1] "ENSMUSG00000026701" "ENSMUSG00000026385" "ENSMUSG00000001270" "ENSMUSG00000001025" "ENSMUSG00000053398"
[1] ""
[1] "ENSMUSG00000034120" "ENSMUSG00000061331" "ENSMUSG00000100131" "ENSMUSG00000100862" "ENSMUSG00000038943"
[1] ""
[1] ""
[1] "PC3"
[1] "ENSMUSG00000010095" "ENSMUSG00000039542" "ENSMUSG00000027562" "ENSMUSG00000058927" "ENSMUSG00000030317"
[1] ""
[1] "ENSMUSG00000021702" "ENSMUSG00000037852" "ENSMUSG00000026728" "ENSMUSG00000001025" "ENSMUSG00000023010"
[1] ""
[1] ""
[1] "PC4"
[1] "ENSMUSG00000004902" "ENSMUSG00000039323" "ENSMUSG00000097971" "ENSMUSG00000035202" "ENSMUSG00000061331"
[1] ""
[1] "ENSMUSG00000030654" "ENSMUSG00000041577" "ENSMUSG00000030905" "ENSMUSG00000027496" "ENSMUSG00000030867"
[1] ""
[1] ""
[1] "PC5"
[1] "ENSMUSG00000021750" "ENSMUSG00000031762" "ENSMUSG00000057666" "ENSMUSG00000004610" "ENSMUSG00000053931"
[1] ""
[1] "ENSMUSG00000020571" "ENSMUSG00000027248" "ENSMUSG00000030342" "ENSMUSG00000027195" "ENSMUSG00000032046"
[1] ""
[1] ""
seurat_sms2 <- ProjectPCA(object = seurat_sms2 )
[1] "PC1"
 [1] "ENSMUSG00000094627" "ENSMUSG00000047945" "ENSMUSG00000003038" "ENSMUSG00000000184" "ENSMUSG00000049775"
 [6] "ENSMUSG00000070713" "ENSMUSG00000020737" "ENSMUSG00000026238" "ENSMUSG00000094790" "ENSMUSG00000001525"
[11] "ENSMUSG00000028832" "ENSMUSG00000046434" "ENSMUSG00000079523" "ENSMUSG00000045128" "ENSMUSG00000004530"
[16] "ENSMUSG00000067274" "ENSMUSG00000032518" "ENSMUSG00000015217" "ENSMUSG00000028639" "ENSMUSG00000030744"
[21] "ENSMUSG00000054717" "ENSMUSG00000025362" "ENSMUSG00000096544" "ENSMUSG00000060143" "ENSMUSG00000098318"
[26] "ENSMUSG00000096006" "ENSMUSG00000057841" "ENSMUSG00000029430" "ENSMUSG00000040952" "ENSMUSG00000032399"
[1] ""
 [1] "ENSMUSG00000006205" "ENSMUSG00000028517" "ENSMUSG00000026424" "ENSMUSG00000041329" "ENSMUSG00000045092"
 [6] "ENSMUSG00000050953" "ENSMUSG00000022037" "ENSMUSG00000004892" "ENSMUSG00000007097" "ENSMUSG00000005360"
[11] "ENSMUSG00000017390" "ENSMUSG00000002985" "ENSMUSG00000020591" "ENSMUSG00000029309" "ENSMUSG00000079037"
[16] "ENSMUSG00000058254" "ENSMUSG00000022564" "ENSMUSG00000005089" "ENSMUSG00000030495" "ENSMUSG00000022132"
[21] "ENSMUSG00000102349" "ENSMUSG00000030310" "ENSMUSG00000028128" "ENSMUSG00000027447" "ENSMUSG00000092341"
[26] "ENSMUSG00000020333" "ENSMUSG00000021508" "ENSMUSG00000030428" "ENSMUSG00000031760" "ENSMUSG00000031517"
[1] ""
[1] ""
[1] "PC2"
 [1] "ENSMUSG00000026701" "ENSMUSG00000037852" "ENSMUSG00000030246" "ENSMUSG00000058135" "ENSMUSG00000001270"
 [6] "ENSMUSG00000026385" "ENSMUSG00000053398" "ENSMUSG00000001025" "ENSMUSG00000018451" "ENSMUSG00000018567"
[11] "ENSMUSG00000024661" "ENSMUSG00000030695" "ENSMUSG00000044080" "ENSMUSG00000027523" "ENSMUSG00000029455"
[16] "ENSMUSG00000040997" "ENSMUSG00000074457" "ENSMUSG00000004558" "ENSMUSG00000032294" "ENSMUSG00000017390"
[21] "ENSMUSG00000033059" "ENSMUSG00000030934" "ENSMUSG00000053931" "ENSMUSG00000024425" "ENSMUSG00000055254"
[26] "ENSMUSG00000029446" "ENSMUSG00000068523" "ENSMUSG00000076441" "ENSMUSG00000024646" "ENSMUSG00000022108"
[1] ""
 [1] "ENSMUSG00000042501" "ENSMUSG00000070495" "ENSMUSG00000102443" "ENSMUSG00000075307" "ENSMUSG00000086607"
 [6] "ENSMUSG00000097452" "ENSMUSG00000002297" "ENSMUSG00000085635" "ENSMUSG00000100768" "ENSMUSG00000050097"
[11] "ENSMUSG00000093684" "ENSMUSG00000092814" "ENSMUSG00000101776" "ENSMUSG00000020914" "ENSMUSG00000096111"
[16] "ENSMUSG00000104329" "ENSMUSG00000036109" "ENSMUSG00000056888" "ENSMUSG00000096061" "ENSMUSG00000103234"
[21] "ENSMUSG00000104060" "ENSMUSG00000021998" "ENSMUSG00000069892" "ENSMUSG00000038943" "ENSMUSG00000036815"
[26] "ENSMUSG00000019942" "ENSMUSG00000061331" "ENSMUSG00000097695" "ENSMUSG00000102858" "ENSMUSG00000104377"
[1] ""
[1] ""
[1] "PC3"
 [1] "ENSMUSG00000021508" "ENSMUSG00000006205" "ENSMUSG00000036949" "ENSMUSG00000027562" "ENSMUSG00000033998"
 [6] "ENSMUSG00000030317" "ENSMUSG00000039542" "ENSMUSG00000026424" "ENSMUSG00000063524" "ENSMUSG00000032281"
[11] "ENSMUSG00000030235" "ENSMUSG00000010095" "ENSMUSG00000002475" "ENSMUSG00000049612" "ENSMUSG00000040055"
[16] "ENSMUSG00000020644" "ENSMUSG00000030310" "ENSMUSG00000028128" "ENSMUSG00000035237" "ENSMUSG00000003974"
[21] "ENSMUSG00000066026" "ENSMUSG00000031467" "ENSMUSG00000032014" "ENSMUSG00000001260" "ENSMUSG00000033208"
[26] "ENSMUSG00000030495" "ENSMUSG00000032349" "ENSMUSG00000043496" "ENSMUSG00000031604" "ENSMUSG00000020614"
[1] ""
 [1] "ENSMUSG00000026728" "ENSMUSG00000026185" "ENSMUSG00000034892" "ENSMUSG00000028234" "ENSMUSG00000031548"
 [6] "ENSMUSG00000021702" "ENSMUSG00000021087" "ENSMUSG00000050621" "ENSMUSG00000007892" "ENSMUSG00000045128"
[11] "ENSMUSG00000046364" "ENSMUSG00000093674" "ENSMUSG00000023169" "ENSMUSG00000032518" "ENSMUSG00000025362"
[16] "ENSMUSG00000071415" "ENSMUSG00000090733" "ENSMUSG00000070498" "ENSMUSG00000019539" "ENSMUSG00000037805"
[21] "ENSMUSG00000060019" "ENSMUSG00000083219" "ENSMUSG00000041841" "ENSMUSG00000067288" "ENSMUSG00000046330"
[26] "ENSMUSG00000039001" "ENSMUSG00000049775" "ENSMUSG00000001025" "ENSMUSG00000037852" "ENSMUSG00000057322"
[1] ""
[1] ""
[1] "PC4"
 [1] "ENSMUSG00000103234" "ENSMUSG00000004902" "ENSMUSG00000100768" "ENSMUSG00000101776" "ENSMUSG00000039323"
 [6] "ENSMUSG00000097695" "ENSMUSG00000097551" "ENSMUSG00000101749" "ENSMUSG00000102443" "ENSMUSG00000083594"
[11] "ENSMUSG00000102858" "ENSMUSG00000061331" "ENSMUSG00000035202" "ENSMUSG00000033981" "ENSMUSG00000063730"
[16] "ENSMUSG00000048148" "ENSMUSG00000104060" "ENSMUSG00000085328" "ENSMUSG00000087267" "ENSMUSG00000103322"
[21] "ENSMUSG00000087306" "ENSMUSG00000042501" "ENSMUSG00000097156" "ENSMUSG00000104329" "ENSMUSG00000035694"
[26] "ENSMUSG00000044519" "ENSMUSG00000101111" "ENSMUSG00000094472" "ENSMUSG00000078808" "ENSMUSG00000104377"
[1] ""
 [1] "ENSMUSG00000019942" "ENSMUSG00000023505" "ENSMUSG00000005233" "ENSMUSG00000027715" "ENSMUSG00000012443"
 [6] "ENSMUSG00000028873" "ENSMUSG00000024056" "ENSMUSG00000023015" "ENSMUSG00000001403" "ENSMUSG00000030677"
[11] "ENSMUSG00000027469" "ENSMUSG00000022033" "ENSMUSG00000020897" "ENSMUSG00000020914" "ENSMUSG00000034906"
[16] "ENSMUSG00000048327" "ENSMUSG00000035683" "ENSMUSG00000048922" "ENSMUSG00000038943" "ENSMUSG00000030867"
[21] "ENSMUSG00000003779" "ENSMUSG00000017716" "ENSMUSG00000027496" "ENSMUSG00000041431" "ENSMUSG00000062248"
[26] "ENSMUSG00000027306" "ENSMUSG00000026683" "ENSMUSG00000020808" "ENSMUSG00000038379" "ENSMUSG00000040084"
[1] ""
[1] ""
[1] "PC5"
 [1] "ENSMUSG00000019942" "ENSMUSG00000027715" "ENSMUSG00000005233" "ENSMUSG00000001403" "ENSMUSG00000003779"
 [6] "ENSMUSG00000028873" "ENSMUSG00000020914" "ENSMUSG00000048327" "ENSMUSG00000017716" "ENSMUSG00000027469"
[11] "ENSMUSG00000023015" "ENSMUSG00000030867" "ENSMUSG00000012443" "ENSMUSG00000030677" "ENSMUSG00000020808"
[16] "ENSMUSG00000020897" "ENSMUSG00000062248" "ENSMUSG00000038943" "ENSMUSG00000041431" "ENSMUSG00000048922"
[21] "ENSMUSG00000024056" "ENSMUSG00000029910" "ENSMUSG00000035683" "ENSMUSG00000023505" "ENSMUSG00000039396"
[26] "ENSMUSG00000022033" "ENSMUSG00000026683" "ENSMUSG00000034906" "ENSMUSG00000027306" "ENSMUSG00000006398"
[1] ""
 [1] "ENSMUSG00000027248" "ENSMUSG00000020571" "ENSMUSG00000007891" "ENSMUSG00000032046" "ENSMUSG00000021094"
 [6] "ENSMUSG00000029838" "ENSMUSG00000030342" "ENSMUSG00000025351" "ENSMUSG00000027195" "ENSMUSG00000030605"
[11] "ENSMUSG00000032324" "ENSMUSG00000020591" "ENSMUSG00000019818" "ENSMUSG00000037089" "ENSMUSG00000008140"
[16] "ENSMUSG00000015575" "ENSMUSG00000037706" "ENSMUSG00000031447" "ENSMUSG00000030062" "ENSMUSG00000022382"
[21] "ENSMUSG00000020570" "ENSMUSG00000033629" "ENSMUSG00000022108" "ENSMUSG00000032383" "ENSMUSG00000024150"
[26] "ENSMUSG00000037720" "ENSMUSG00000026223" "ENSMUSG00000030286" "ENSMUSG00000024121" "ENSMUSG00000029778"
[1] ""
[1] ""
seurat_sms2 <- JackStraw(object = seurat_sms2  )
PCElbowPlot(object = seurat_sms2)

seurat_sms2 <- SetAllIdent(object = seurat_sms2 , id = "type")
PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 2)

PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 3)

PCAPlot(object = seurat_sms2 , dim.1 = 2, dim.2 = 3)

PCAPlot(object = seurat_sms2 , dim.1 = 1, dim.2 = 4)

PCAPlot(object = SetAllIdent( seurat_sms2 , id = "age" ) , dim.1 = 1, dim.2 = 4)

Log transform the TPM values

smartseq2_data <- log(1+smartseq2_data)

Make a matrix of the data

data_matrix_celltypes <- lapply( X = celltypes, FUN = function(x){
                        cells <- filter(smartseq2_annotation , type == x) %>% pull(cell) %>% as.character()
                        # t(as.matrix(smartseq2_data[,cells]))
                        
                        FetchData(object = seurat_sms2 , vars.all = c("PC1","PC2","PC3","PC4","PC5") , cells.use = cells )
                      })

Now we calculate the euclidean distance between all the cells from one celltype

euc_dist_celltypes <- lapply( data_matrix_celltypes , FUN = function(x){as.matrix(dist(x = x, method = "euclidean" , upper = TRUE))} )
pheatmap(
  main = celltypes[[1]],
  mat = euc_dist_celltypes[[1]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = celltypes[[2]],
  mat = euc_dist_celltypes[[2]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = celltypes[[3]],
  mat = euc_dist_celltypes[[3]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = celltypes[[4]],
  mat = euc_dist_celltypes[[4]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = celltypes[[5]],
  mat = euc_dist_celltypes[[5]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

Compare all samples to each other

rownames(smartseq2_annotation) <- NULL
anno <- smartseq2_annotation %>% mutate(type = factor(type , levels = c("qNSC1","qNSC2","aNSC1","aNSC2","Astro"))) %>% arrange(age , type) %>% column_to_rownames( var = "cell")
dist_all_samples <- as.matrix(dist(x = t(as.matrix(smartseq2_data)[,rownames(anno)]), method = "euclidean" , upper = TRUE))
pheatmap(
  main = "Euclidean Distance between all samples",
  mat = dist_all_samples,
  cluster_rows = FALSE, 
  cluster_cols = FALSE,
  annotation_row = anno,
  annotation_col = anno,
  annotation_colors = list( type = c( qNSC1 = "steelblue" , qNSC2 = "steelblue1" , aNSC1 = "tomato" , aNSC2 = "sienna1", Astro = "grey") , age = c(young = "forestgreen" , old = "red")) ,
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

Density of euclidean distances

df.plot.list <- lapply( X = euc_dist_celltypes, FUN = function(x){
                                            x %>% as.data.frame() %>% rownames_to_column("cell1") %>% gather(key = "cell2" , value = "euclidean_distance" , -cell1) %>% left_join( y = dplyr::rename(anno, age_cell1 = age) %>% rownames_to_column( var = "cell1") , by = "cell1" ) %>% left_join( y = dplyr::rename(anno, age_cell2 = age) %>% rownames_to_column( var = "cell2") , by = "cell2" ) %>% mutate(comparison = paste(age_cell1 , age_cell2 , sep = "_")) %>% dplyr::filter(comparison %in% c("old_old","young_old","young_young"))
})
gg.list <- lapply( X = df.plot.list, FUN = function(x){
                                            ggplot(data = x, mapping = aes(x = euclidean_distance , color = comparison , fill = comparison )) + geom_density( alpha = 0.3) + ggtitle( paste0(unique(as.character(x$type.x))) )
})

Astro

print(gg.list[[1]])

aNSC1

print(gg.list[[2]])

aNSC2

print(gg.list[[3]])

qNSC1

print(gg.list[[4]])

qNSC2

print(gg.list[[5]])

Euclidean Distances between celltypes

celltype_comparisons <- list(Astro_qNSC1 = c("Astro","qNSC1") , qNSC1_qNSC2 = c("qNSC1","qNSC2") , qNSC2_aNSC1 = c("qNSC2","aNSC1") , aNSC1_aNSC2 = c("aNSC1","aNSC2") , qNSC1_aNSC2 = c("qNSC1","aNSC2")  )
celltype_comparisons
$Astro_qNSC1
[1] "Astro" "qNSC1"

$qNSC1_qNSC2
[1] "qNSC1" "qNSC2"

$qNSC2_aNSC1
[1] "qNSC2" "aNSC1"

$aNSC1_aNSC2
[1] "aNSC1" "aNSC2"

$qNSC1_aNSC2
[1] "qNSC1" "aNSC2"

Make a matrix of the data

data_matrix_lineage <- lapply( X = celltype_comparisons, FUN = function(x){
                        cells <- filter(smartseq2_annotation , type %in% x) %>% pull(cell) %>% as.character()
                        # t(as.matrix(smartseq2_data[,cells]))
                        
                        FetchData(object = seurat_sms2 , vars.all = c("PC1","PC2","PC3","PC4","PC5") , cells.use = cells )
                      })

Now we calculate the euclidean distance between all the cells from the comparison

euc_dist_lineage_all <- lapply( data_matrix_lineage , FUN = function(x){as.matrix(dist(x = x, method = "euclidean" , upper = TRUE))} )
pheatmap(
  main = paste(celltype_comparisons[[1]], collapse = "_vs_"),
  mat = euc_dist_lineage_all[[1]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = paste(celltype_comparisons[[2]], collapse = "_vs_"),
  mat = euc_dist_lineage_all[[2]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = paste(celltype_comparisons[[3]], collapse = "_vs_"),
  mat = euc_dist_lineage_all[[3]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = paste(celltype_comparisons[[4]], collapse = "_vs_"),
  mat = euc_dist_lineage_all[[4]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

pheatmap(
  main = paste(celltype_comparisons[[5]], collapse = "_vs_"),
  mat = euc_dist_lineage_all[[5]],
  cluster_rows = FALSE, 
  cluster_cols = FALSE, 
  show_rownames = TRUE , 
  show_colnames = TRUE , 
  display_numbers = FALSE , 
  number_color = "black" , 
  fontsize = 14
)

Density of euclidean distances

df.plot.list_all <- lapply( X = euc_dist_lineage_all, FUN = function(x){
                                            x %>% as.data.frame() %>% rownames_to_column("cell1") %>% gather(key = "cell2" , value = "euclidean_distance" , -cell1) %>% left_join( y = dplyr::rename(anno, type_cell1 = type) %>% rownames_to_column( var = "cell1") , by = "cell1" ) %>% left_join( y = dplyr::rename(anno, type_cell2 = type) %>% rownames_to_column( var = "cell2") , by = "cell2" ) %>% mutate(comparison = paste(type_cell1 , type_cell2 , sep = "_"))
})
gg.list_all <- lapply( X = df.plot.list_all, FUN = function(x){
                                            ggplot(data = x, mapping = aes(x = euclidean_distance , color = comparison)) + geom_density() + ggtitle( "" )
})
print(gg.list_all[[1]])

print(gg.list_all[[2]])

print(gg.list_all[[3]])

print(gg.list_all[[4]])

print(gg.list_all[[5]])

Euclidean distances young vs old

q1_q2_euc_dist <- df.plot.list_all$qNSC1_qNSC2 %>% filter(comparison == "qNSC1_qNSC2")
df.plot.list_ref <- lapply( X = euc_dist_celltypes, FUN = function(x){
                                            x  %>% as.data.frame() %>% rownames_to_column("cell1") %>% gather(key = "cell2" , value = "euclidean_distance" , -cell1) %>% left_join( y = dplyr::rename(anno, age_cell1 = age) %>% rownames_to_column( var = "cell1") , by = "cell1" ) %>% left_join( y = dplyr::rename(anno, age_cell2 = age) %>% rownames_to_column( var = "cell2") , by = "cell2" ) %>% mutate(comparison = paste(age_cell1 , age_cell2 , sep = "_")) %>% dplyr::mutate(type = as.character(type.x) ) %>% dplyr::select( cell1,cell2,euclidean_distance,comparison , type) %>% bind_rows(q1_q2_euc_dist %>% dplyr::mutate(type = as.character(type_cell1) ) %>% dplyr::select( cell1,cell2,euclidean_distance,comparison,type)) %>% dplyr::filter(comparison %in% c("old_old","young_old","young_young","qNSC1_qNSC2")) %>% mutate(comparison = factor(comparison , levels = c("old_old","young_old","young_young","qNSC1_qNSC2")))
})
colors_comparisons <- c("old_old" = "slateblue" ,"young_old" = "deepskyblue4", "young_young" = "olivedrab" , "qNSC1_qNSC2" = "black")
gg.list <- lapply( X = df.plot.list_ref, FUN = function(x){
                                            ggplot(data = x, mapping = aes(x = euclidean_distance , color = comparison , fill = comparison )) + geom_density( alpha = 0.3) + ggtitle( paste0(unique(as.character(x$type))) ) + xlab("Euclidean Distance") + ylab("Density") + scale_fill_manual(values = colors_comparisons) + scale_color_manual( values = colors_comparisons  ) + labs(color="Comparison",fill="Comparison") + ggtitle( paste0(unique(as.character(x$type))) )
})

Astro

print(gg.list[[1]])

aNSC1

print(gg.list[[2]])

aNSC2

print(gg.list[[3]])

qNSC1

print(gg.list[[4]])

qNSC2

print(gg.list[[5]])

qNSC1 and Astrocytes

BoxPlotSmart <- function( x , anno , idents , genes , trans_log2 = TRUE , pt.alpha = 1 , facet_switch = FALSE ){
  require(dplyr)
  require(tidyr)
  require(ggplot2)
  require(ggbeeswarm)
  require(cowplot)
  require(hash)
  ens2gene_hash <- hash( keys = genes , values = names(genes) )
  
  cells <- as.character( filter( anno , type %in% idents ) %>% pull("cell") )
  
  data_violin <- dplyr::select(x , one_of( c( "gene_id" , cells ) ) ) %>% filter( gene_id %in% genes )
  
  data_violin_gather <- gather( data = data_violin , key = "cell" , value = "TPM" , -gene_id   )
  
  if(trans_log2){ data_violin_gather$TPM <- log2( data_violin_gather$TPM + 1 ) }
  
  data_violin_gather_joined <- left_join(x = data_violin_gather , y = anno, by = "cell")
  
  print( data_violin_gather_joined  %>% group_by(gene_id,type) %>% summarise( percent = sum(TPM > 0)/length(TPM) ) , gene_id = gene_id )
  
  gene_ids <- hash::values(ens2gene_hash[genes])
  gene_ids <- gene_ids[! is.na(gene_ids)]
  genes_labeller_vec <- gene_ids
  genes_labeller <- labeller(gene_id = genes_labeller_vec)
  
  data_violin_gather_joined <- dplyr::filter(data_violin_gather_joined , gene_id %in% names(genes_labeller_vec) )
  
  g <- ggplot(data = data_violin_gather_joined , mapping = aes(x = type , y = TPM , fill = type )) + 
        geom_boxplot( outlier.shape = NA ) +    
        geom_quasirandom(alpha = pt.alpha , color = "black" , size = 0.7 ) +
        scale_x_discrete( name = "Identity") + 
        scale_y_continuous(name = if(trans_log2){"log2( TPM + 1 )"}else{"TPM"}) + 
        scale_fill_manual(name = "Identity" , values = c( qNSC1 = "steelblue" , qNSC2 = "steelblue1" , Astro = "grey50" ) ) +
        if( all( c("old","young") %in% as.character(anno$age) ) ){
          if(! facet_switch){
            facet_grid(facets = gene_id~age , labeller = genes_labeller)
          }else{
            facet_grid(facets = age~gene_id , labeller = genes_labeller)    
          }      
        }else{
          facet_wrap( facets = "gene_id" , ncol = 1 , labeller = genes_labeller  )
        }
    
  
  return(g)
}

Load the data

Load the SmartSeq2 data for young and old separately

smartseq_data_old <- read.csv(file = "count_table/TPM_NSC_and_Astro/old/Gene_expression_matrix_TPM_old.csv" , header = TRUE, row.names = 1)
smartseq_data_young <- read.csv(file = "count_table/TPM_NSC_and_Astro/young/Gene_expression_matrix_TPM_young.csv" , header = TRUE, row.names = 1)

Join young and old

# smartseq_data <- full_join(x = smartseq_data_old , y = smartseq_data_young)

and the cell annotation to celltypes

smartseq_data_annotation_old <- read.csv(file = "count_table/cell_annotation_NSC_Astro/old/cell_annotation_old.csv" , header = TRUE, row.names = 1)
smartseq_data_annotation_young <- read.csv(file = "count_table/cell_annotation_NSC_Astro/young/cell_annotation_young.csv" , header = TRUE, row.names = 1)

Join young and old

# smartseq_data_annotation <- bind_rows( smartseq_data_annotation_old, smartseq_data_annotation_young )

Boxplot Cd9

BoxPlotSmart(x = smartseq_data_old , anno = smartseq_data_annotation_old , idents = c("qNSC1","Astro") , genes = c(Cd9 = "ENSMUSG00000030342") )
Column `cell` joining character vector and factor, coercing into character vector

cd9plot_old <- BoxPlotSmart(x = smartseq_data_old , anno = smartseq_data_annotation_old , idents = c("qNSC1","Astro") , genes = c(Cd9 = "ENSMUSG00000030342") , pt.alpha = 1) + theme(legend.position = "none") 
Column `cell` joining character vector and factor, coercing into character vector
cd9plot_old

cd9plot_young <- BoxPlotSmart(x = smartseq_data_young , anno = smartseq_data_annotation_young , idents = c("qNSC1","Astro") , genes = c(Cd9 = "ENSMUSG00000030342") , pt.alpha = 1) + theme(legend.position = "none") 
Column `cell` joining character vector and factor, coercing into character vector
cd9plot_young

Heatmap differentially expressed genes

Load the lists of differentially expressed genes between cortical Astrocytes and qNSC1s, for cells from old mice.

# Old 
DEgenes_old_tab <- read.csv(file = "results/q1_old_vs_q1_oldAstro_sig_results.csv")
DEgenes_old_tab$gene_name <- str_to_title(DEgenes_old_tab$gene_name)
ens2gene_old <- DEgenes_old_tab 
DEgenes_old_up <- dplyr::filter(DEgenes_old_tab , log_fold_chang > 0 , ! is.na(gene_id))
DEgenes_old_down <- dplyr::filter(DEgenes_old_tab , log_fold_chang < 0 , ! is.na(gene_id))
seurat_10X2 <- readRDS(file = "../10X/seurat_10X2_clustered_min_1500_nGene.RDS")
DEgenes_old_up_comp <- dplyr::filter(DEgenes_old_up , gene_name %in% rownames(seurat_10X2@data) ) 
DEgenes_old_down_comp <- dplyr::filter(DEgenes_old_down , gene_name %in% rownames(seurat_10X2@data) ) 
# DEgenes_old_up_comp <- dplyr::filter(DEgenes_old_up , gene_id %in% smartseq_data_old$gene_id ) 
# DEgenes_old_down_comp <- dplyr::filter(DEgenes_old_down , gene_id %in% smartseq_data_old$gene_id )  
# DEgenes_old <- c( as.character(DEgenes_old_up$gene_name) , as.character(DEgenes_old_down$gene_name) )  
DEgenes_old_ens <- c( as.character(DEgenes_old_up$gene_id) , as.character(DEgenes_old_down$gene_id) )  
anno_old <- read.csv(file = "count_table/cell_annotation_NSC_Astro/old/cell_annotation_old.csv")

Filter the SMARTseq2 TPM values for the genes that are differentially expressed

q1cells <- filter(anno_old, type == "qNSC1") 
q2cells <- filter(anno_old, type == "qNSC2") 
astro_cells <- filter(anno_old, type == "Astro") 
up_gene_id <- as.character(DEgenes_old_up_comp$gene_id)
down_gene_id <- as.character(DEgenes_old_down_comp$gene_id)
up_gene_names <- as.character(DEgenes_old_up_comp$gene_name) 
down_gene_names <- as.character(DEgenes_old_down_comp$gene_name)
scale_red_white <- colorRampPalette(colors = c("red","white"))

Fetch the data from qNSC1, qNSC2 and Astrocytes for the genes

df.heatmap.smart_up_comp <- smartseq_data_old %>% dplyr::select( one_of(c("gene_id",as.character(q2cells$cell),as.character(q1cells$cell),as.character(astro_cells$cell))) ) %>% dplyr::filter(gene_id %in% up_gene_id ) %>% arrange(gene_id)
df.heatmap.smart_down_comp <- smartseq_data_old %>% dplyr::select( one_of(c("gene_id",as.character(q2cells$cell),as.character(q1cells$cell),as.character(astro_cells$cell)))  ) %>% dplyr::filter(gene_id %in% down_gene_id ) %>% arrange(gene_id)
df.heatmap.smart_comp <- as.matrix( bind_rows( df.heatmap.smart_up_comp , df.heatmap.smart_down_comp ) %>% column_to_rownames("gene_id") )
df.heatmap.smart_comp <- log( as.matrix(df.heatmap.smart_comp) + 1 )
# df.heatmap.smart_comp <- t(scale(x = t(df.heatmap.smart_comp) , center = TRUE , scale = TRUE ))
anno_sms2 <- anno_old %>% dplyr::select(cell,type) %>% column_to_rownames("cell")

Plot Heatmap

hm_sms2_comp <- pheatmap(mat = pmax( pmin(df.heatmap.smart_comp,3) , -3 ) , cluster_rows = FALSE , cluster_cols = FALSE , color = rev(scale_red_white(200))  , breaks = seq(from=0,to=3,length.out = 200) , main = "log( TPM + 1 )" , show_colnames = FALSE , show_rownames = FALSE , gaps_row = 170 , gaps_col = c(17,113) , fontsize = 8 , annotation_col = anno_sms2 , annotation_colors = list( type = c(qNSC1="steelblue",qNSC2="steelblue1",Astro="grey"))  )

SessionInfo

sessionInfo()
R version 3.4.3 (2017-11-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04.3 LTS

Matrix products: default
BLAS: /usr/lib/libblas/libblas.so.3.6.0
LAPACK: /usr/lib/lapack/liblapack.so.3.6.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] hash_2.2.6                 ggbeeswarm_0.6.0           ggrepel_0.8.0              genefilter_1.60.0         
 [5] BiocParallel_1.12.0        DESeq2_1.16.1              SummarizedExperiment_1.8.1 DelayedArray_0.4.1        
 [9] matrixStats_0.53.1         GenomicRanges_1.30.3       GenomeInfoDb_1.14.0        pheatmap_1.0.10           
[13] bindrcpp_0.2               org.Mm.eg.db_3.5.0         AnnotationDbi_1.40.0       IRanges_2.12.0            
[17] S4Vectors_0.16.0           Seurat_2.2.0               cowplot_0.7.0              clusterProfiler_3.4.4     
[21] DOSE_3.4.0                 gridExtra_2.2.1            forcats_0.3.0              stringr_1.3.1             
[25] dplyr_0.7.4                purrr_0.2.4                readr_1.1.1                tidyr_0.7.2               
[29] tibble_1.4.2               ggplot2_2.2.1              tidyverse_1.2.1            Matrix_1.2-14             
[33] Biobase_2.38.0             BiocGenerics_0.24.0       

loaded via a namespace (and not attached):
  [1] R.utils_2.6.0          tidyselect_0.2.3       lme4_1.1-18-1          RSQLite_2.1.1          htmlwidgets_1.2       
  [6] grid_3.4.3             trimcluster_0.1-2      ranger_0.6.0           Rtsne_0.11             munsell_0.4.3         
 [11] codetools_0.2-15       ica_1.0-2              colorspace_1.3-2       GOSemSim_2.4.1         knitr_1.20            
 [16] rstudioapi_0.7         ROCR_1.0-7             robustbase_0.92-7      dtw_1.20-1             NMF_0.20.6            
 [21] labeling_0.3           lars_1.2               GenomeInfoDbData_1.0.0 mnormt_1.5-5           bit64_0.9-7           
 [26] rprojroot_1.3-2        diptest_0.75-7         R6_2.2.2               doParallel_1.0.10      VGAM_1.0-3            
 [31] locfit_1.5-9.1         flexmix_2.3-13         bitops_1.0-6           fgsea_1.4.1            assertthat_0.2.0      
 [36] SDMTools_1.1-221       scales_0.5.0           nnet_7.3-12            beeswarm_0.2.3         gtable_0.2.0          
 [41] rlang_0.2.2            MatrixModels_0.4-1     scatterplot3d_0.3-41   splines_3.4.3          lazyeval_0.2.0        
 [46] ModelMetrics_1.1.0     acepack_1.4.1          broom_0.4.3            checkmate_1.8.5        yaml_2.2.0            
 [51] reshape2_1.4.2         abind_1.4-5            modelr_0.1.1           backports_1.1.2        qvalue_2.10.0         
 [56] Hmisc_4.1-1            caret_6.0-73           tools_3.4.3            psych_1.7.8            gridBase_0.4-7        
 [61] gplots_3.0.1           RColorBrewer_1.1-2     proxy_0.4-22           ggridges_0.5.0         Rcpp_0.12.18          
 [66] plyr_1.8.4             base64enc_0.1-3        zlibbioc_1.24.0        RCurl_1.95-4.10        rpart_4.1-12          
 [71] pbapply_1.3-1          haven_1.1.2            cluster_2.0.6          magrittr_1.5           data.table_1.11.6     
 [76] DO.db_2.9              openxlsx_4.1.0         mvtnorm_1.0-5          evaluate_0.11          hms_0.4.2             
 [81] xtable_1.8-2           XML_3.98-1.11          rio_0.5.10             mclust_5.2.2           readxl_1.1.0          
 [86] compiler_3.4.3         KernSmooth_2.23-15     crayon_1.3.4           minqa_1.2.4            R.oo_1.22.0           
 [91] htmltools_0.3.6        segmented_0.5-1.4      Formula_1.2-3          geneplotter_1.56.0     tclust_1.2-3          
 [96] lubridate_1.7.1        DBI_1.0.0              diffusionMap_1.1-0.1   MASS_7.3-48            fpc_2.1-10            
[101] boot_1.3-20            car_3.0-2              cli_1.0.0              R.methodsS3_1.7.1      gdata_2.17.0          
[106] bindr_0.1              igraph_1.0.1           pkgconfig_2.0.2        sn_1.5-0               rvcheck_0.1.0         
[111] registry_0.3           numDeriv_2016.8-1      foreign_0.8-69         xml2_1.1.1             foreach_1.4.3         
[116] annotate_1.56.2        vipor_0.4.5            rngtools_1.2.4         pkgmaker_0.22          XVector_0.18.0        
[121] rvest_0.3.2            digest_0.6.12          tsne_0.1-3             rmarkdown_1.10         cellranger_1.1.0      
[126] fastmatch_1.1-0        htmlTable_1.12         curl_3.2               kernlab_0.9-25         gtools_3.5.0          
[131] modeltools_0.2-22      nloptr_1.0.4           nlme_3.1-131           jsonlite_1.5           carData_3.0-1         
[136] viridisLite_0.3.0      pillar_1.3.0           lattice_0.20-35        httr_1.3.1             DEoptimR_1.0-8        
[141] survival_2.41-3        GO.db_3.5.0            glue_1.3.0             zip_1.0.0              FNN_1.1               
[146] prabclus_2.2-6         iterators_1.0.8        bit_1.1-14             class_7.3-14           stringi_1.2.4         
[151] mixtools_1.0.4         blob_1.1.1             latticeExtra_0.6-28    caTools_1.17.1         memoise_1.0.0         
[156] irlba_2.1.2            ape_5.1               
LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2Ygb2xkIGFuZCB5b3VuZyBuZXVyYWwgc3RlbSBjZWxscyBzZXF1ZW5jZWQgd2l0aCB0aGUgU21hcnRTZXEyIHByb3RvY29sIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgc21hcnQ6IG5vCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgojIExvYWQgZGF0YSBmb3IgeW91bmcgYW5kIG9sZCBuZXVyYWwgc3RlbSBjZWxscyBzZXF1ZW5jZWQgd2l0aCB0aGUgU21hcnQtU2VxMiBwcm90b2NvbAoKYGBge3J9Ck5TQ3NfYW5ub3RhdGlvbiA8LSByZWFkLmNzdihmaWxlID0gImNvdW50X3RhYmxlL05TQ3NfYW5ub3RhdGlvbi5jc3YiICwgcm93Lm5hbWVzID0gMSkKClRQTV9OU0NzIDwtIHJlYWQuY3N2KGZpbGUgPSAiY291bnRfdGFibGUvVFBNX05TQ3MuY3N2IiAsIHJvdy5uYW1lcyA9IDEpCmBgYAoKTWFrZSB0aGUgY2VsbCBuYW1lcyBhbHNvIHJvd25hbWVzCgpgYGB7cn0Kcm93bmFtZXMoTlNDc19hbm5vdGF0aW9uKSA8LSBOU0NzX2Fubm90YXRpb24kY2VsbAoKaGVhZCggTlNDc19hbm5vdGF0aW9uICkKYGBgCgojIExvYWQgdGhlIFIgcGFja2FnZXMgbmVlZGVkIGZvciB0aGUgYW5hbHlzaXMKCldlIG5lZWQgdGhlIE1hdHJpeCBwYWNrYWdlIHRvIHVzZSBzcGFyc2UgbWF0cmljZXMgdG8gc2F2ZSBtZW1vcnkgd2hpbGUgY29tcHV0aW5nLiBUaGUgZ2dwbG90MiBwYWNrYWdlIGlzIHVzZWQgZm9yIHBsb3R0aW5nLiBTZXVyYXQgaXMgdXNlZCB0byBjcmVhdGUgUENBIGFuZCB0U05FIHBsb3RzLiAKCmBgYHtyfQpyZXF1aXJlKE1hdHJpeCkKcmVxdWlyZSh0aWR5dmVyc2UpCnJlcXVpcmUoZ2dwbG90MikKcmVxdWlyZShncmlkRXh0cmEpCgpyZXF1aXJlKGNsdXN0ZXJQcm9maWxlcikKcmVxdWlyZShTZXVyYXQpCmBgYAoKYGBge3J9CnNldC5zZWVkKDEyMykKYGBgCgpMb2FkIHRoZSBtb25vY2xlIHBzZXVkb3RpbWUgcmVzdWx0cwoKYGBge3J9CnBzZXVkb3RpbWVfb3JkZXJpbmcgPC0gcmVhZC5jc3YoZmlsZSA9ICJNb25vY2xlL3BzZXVkb3RpbWVfb3JkZXJpbmcuY3N2IiAsIHJvdy5uYW1lcyA9IDEgKQpgYGAKCgojIENoZWNrIGlubmF0ZSBpbW11bmUgcmVzcG9uc2UgYW5kIGludGVyZmVyb24gcmVzcG9uc2UgR08gY2F0ZWdvcnkgZ2VuZXMKCiMjIENyZWF0ZSBhIFNldXJhdCBvYmplY3QgdXNpbmcgdGhlIFRQTSB2YWx1ZXMgZm9yIHRoZSBTbWFydFNlcTIgZGF0YSBhbmQgdXNlIHRoZSBzYW1lIG5vcm1hbGl6YXRpb24gc3RyYXRlZ3kgYXMgZm9yIHRoZSAxMFggc2VxdWVuY2luZyBydW4uCgpVc2UgdGhlIFRQTSBkYXRhLmZyYW1lIHRvIGluaXRpYWxpemUgYSBTZXVyYXQgb2JqZWN0CgpgYGB7cn0KVFBNX05TQyA8LSByZW1vdmVfcm93bmFtZXMoVFBNX05TQ3MpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoIHZhciA9ICJlbnNlbWJsX2dlbmVfaWQiKQoKc2V1cmF0X3NtczIgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KHJhdy5kYXRhID0gVFBNX05TQyAgLCBtaW4uY2VsbHMgPSAzLCBwcm9qZWN0ID0gInlvdW5nX3ZzX29sZF9TbWFydFNlcTIiKQpgYGAKClNldCBpZGVudGl0eSB0byBOU0MgdG8gYmVnaW4gd2l0aC4KCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBTZXRJZGVudChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGlkZW50LnVzZSA9ICJOU0MiKQpgYGAKCgpgYGB7cn0KVmxuUGxvdChvYmplY3QgPSBzZXVyYXRfc21zMiwgZmVhdHVyZXMucGxvdCA9IGMoIm5HZW5lIiwgIm5VTUkiKSkKYGBgCgpBZGQgbWV0YWRhdGE6IGFnZSBvZiB0aGUgYW5pbWFsLCBjZWxsIG5hbWUgYW5kIGNlbGx0eXBlIChhY3RpdmF0aW9uIHN0YXRlKQoKYGBge3J9CnNldXJhdF9zbXMyIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IHNldXJhdF9zbXMyLCBtZXRhZGF0YSA9IE5TQ3NfYW5ub3RhdGlvbiApCmBgYAoKTG9nLW5vcm1hbGl6ZSB0aGUgVFBNIGRhdGEKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IHNldXJhdF9zbXMyLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiKQpgYGAKCgpgYGB7ciByZXN1bHRzPSdoaWRlJ30Kc2V1cmF0X3NtczIgPC0gU2NhbGVEYXRhKG9iamVjdCA9IHNldXJhdF9zbXMyLCB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJuVU1JIiwgIm5HZW5lIikpCmBgYAoKIyMjIFJlZ3Jlc3Mgb3V0IGRpZmZlcmVuY2UgYmV0d2VlbiBTIHBoYXNlIGFuZCBHMi9NIFBoYXNlCgpGaXJzdCB3ZSBsb2FkIHRoZSBnZW5lcyByZWxhdGVkIHRvIHRoZSBjZWxsIGN5Y2xlIHBoYXNlcyBHMi9NIGFuZCBTIGFuZCBtYWtlIHRoZW0gbWF0Y2hpbmcgdG8gdGhlIGdlbmUgc3ltYm9scyBpbiB0aGUgZGF0YXNldCBieSBjb252ZXJ0aW5nIHRvIEVOU0VNQkxfSURzIC4gCgpgYGB7cn0Kcy5nZW5lcyA8LSBiaXRyKGdlbmVJRCA9IHN0cmluZ3I6OnN0cl90b190aXRsZShjYy5nZW5lcyRzLmdlbmVzKSAsIGZyb21UeXBlID0gIlNZTUJPTCIgLCB0b1R5cGUgPSAiRU5TRU1CTCIgLGRyb3AgPSBGQUxTRSAsT3JnRGIgPSAib3JnLk1tLmVnLmRiIikKCmcybS5nZW5lcyA8LSBiaXRyKGdlbmVJRCA9IHN0cmluZ3I6OnN0cl90b190aXRsZShjYy5nZW5lcyRnMm0uZ2VuZXMpICwgZnJvbVR5cGUgPSAiU1lNQk9MIiAsIHRvVHlwZSA9ICJFTlNFTUJMIiAsZHJvcCA9IEZBTFNFICxPcmdEYiA9ICJvcmcuTW0uZWcuZGIiKQoKc2V1cmF0X3NtczIgPC0gQ2VsbEN5Y2xlU2NvcmluZyhvYmplY3QgPSBzZXVyYXRfc21zMiwgcy5nZW5lcyA9IHMuZ2VuZXMkRU5TRU1CTCAsIGcybS5nZW5lcyA9IGcybS5nZW5lcyRFTlNFTUJMICwgc2V0LmlkZW50ID0gRkFMU0UpCmBgYAoKVGhlbiB3ZSBjYWxjdWxhdGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgY2VsbCBjeWNsZSBzY29yZXMgYW5kIHJlZ3Jlc3Mgb3VyIGRhdGEgb24gdGhhdCBkaWZmZXJlbmNlLgoKYGBge3J9CnNldXJhdF9zbXMyQG1ldGEuZGF0YSRDQy5EaWZmZXJlbmNlIDwtIHNldXJhdF9zbXMyQG1ldGEuZGF0YSRTLlNjb3JlIC0gc2V1cmF0X3NtczJAbWV0YS5kYXRhJEcyTS5TY29yZQoKc2V1cmF0X3NtczIgPC0gU2NhbGVEYXRhKG9iamVjdCA9IHNldXJhdF9zbXMyLCB2YXJzLnRvLnJlZ3Jlc3MgPSAiQ0MuRGlmZmVyZW5jZSIsIGRpc3BsYXkucHJvZ3Jlc3MgPSBGQUxTRSkKYGBgCgojIyBMb2FkIGEgbGlzdCBvZiBnZW5lcyBmcm9tIHRoZSBpbm5hdGUgaW1tdW5lIHJlc3BvbnNlIEdPIGNhdGVnb3J5IAoKYGBge3J9CnJlc3VsdHNfaW50ZXJmZXJvbl9yZXNwb25zZV9pbW11bmUgPC0gc3RydWN0dXJlKGxpc3QobWdpX3N5bWJvbCA9IGMoIlViYTciLCAiVWJlMmw2IiwgIlViZTJlMSIsICJVYmUyZTIiLCAKIklzZzE1IiwgIklrYmtlIiwgIlNldGQyIiwgIkEyMzAwNTBQMjBSaWsiLCAiTXgyIiwgIlNobXQyIiwgIklyZ20yIiwgCiJEbmFqYTMiLCAiS3ludSIsICJCc3QyIiwgIlNlYzYxYTEiLCAiQ2l0ZWQxIiwgIkgyLUFhIiwgIlNsYzExYTEiLCAKIkdjaDEiLCAiVWJkIiwgIklsMjNyIiwgIlNsYzMwYTgiLCAiQ3hjbDE2IiwgIkN5cDI3YjEiLCAiVHJpbTIxIiwgCiJJZml0bTIiLCAiSWZpdG0xIiwgIklmaXRtMyIsICJBZGFtdHMxMyIsICJUZ3RwMiIsICJUZ3RwMSIsICJTbmNhIiwgCiJDZDQwIiwgIk1lZnYiLCAiQ2lpdGEiLCAiS2xobDIwIiwgIkFkYXIiLCAiSWZuYXIyIiwgIkVpZjJhazIiLCAKIlBsc2NyMSIsICJMYW1wMyIsICJYYWYxIiwgIlN0YXQxIiwgIlMxMDBhOCIsICJUcmRjIiwgIlMxMDBhOSIsIAoiQWltMiIsICJNYjIxZDEiLCAiSXJmMSIsICJQZ2x5cnA0IiwgIlNkaGFmNCIsICJEZHgzeCIsICJEZWZiMSIsIAoiU2VyaW5jNSIsICJEZHg1OCIsICJEZWZiMTIiLCAiRGVmYjM0IiwgIk5scnAxMCIsICJSZWxhIiwgIkdhdGEzIiwgCiJDc2YxciIsICJJZ2hhIiwgIkRlZmIxNSIsICJSbmFzZTYiLCAiRGVmYjM1IiwgIkRlZmIxMyIsICJQZ2x5cnAzIiwgCiJJZ2hnMmMiLCAiS3J0MTYiLCAiVHJpbCIsICJObHJwOWMiLCAiQnBpZmIzIiwgIlBpazNjYSIsICJObHJwMWEiLCAKIk5scnA5YiIsICJJZ2hnMyIsICJJZ2hkIiwgIklnaG0iLCAiTmxycDFiIiwgIkNmaSIsICJMeTk2IiwgIkpjaGFpbiIsIAoiQzhiIiwgIk5scngxIiwgIkN5YmIiLCAiUG1sIiwgIkM4YSIsICJUbmsxIiwgIlBvbHIzYyIsICJJbDFyYXAiLCAKIlJibTE0IiwgIlBvbHIzZSIsICJBbnhhMSIsICJDZmQiLCAiSWZuayIsICJGY25iIiwgIk5yMWg0IiwgIkRlZmI0MyIsIAoiTm9ubyIsICI1NzMwNTU5QzE4UmlrIiwgIkhtZ2IzIiwgIkRlZmIzMCIsICJTaDJkMWIyIiwgIklnaHY1LTIiLCAKIklnaHYyLTIiLCAiVG5mYWlwOGwyIiwgIlRhcm0xIiwgIklnaHY1LTQiLCAiQnBpZmExIiwgIk5vZDIiLCAKIklnaHYyLTMiLCAiT3R1bGluIiwgIklnaHY1LTYiLCAiQnBpZmIxIiwgIklmaTIwMmIiLCAiSWdodjUtOSIsIAoiRmNncjEiLCAiVHJpbTI4IiwgIkFyZzEiLCAiVHJiYzEiLCAiUGlrM2NnIiwgIkRlZmIxOCIsICJEZWZiNDEiLCAKIklnaHYyLTUiLCAiSWdodjUtMTIiLCAiSWdodjItNiIsICJJZ2h2NS05LTEiLCAiUG9scjNnIiwgIkN5bGQiLCAKIlNoMmQxYSIsICJaYXA3MCIsICJJZml0MyIsICJSc2FkMiIsICJNc3JiMSIsICJJZml0MSIsICJDcjFsIiwgCiJDZnAiLCAiU3AxMTAiLCAiVHJiYzIiLCAiQ2FzcDQiLCAiTm9kMSIsICJTbGEyIiwgIlNtcGRsM2IiLCAKIlRscjUiLCAiSWdodjUtMTItNCIsICJJZ2h2Mi05LTEiLCAiQXhsIiwgIk1hcDNrNSIsICJDZDU1IiwgIkJsayIsIAoiTXlkODgiLCAiVG5mc2Y0IiwgIklnaHYyLTYtOCIsICJJZ2h2Mi03IiwgIklnaHY1LTE1IiwgIklnaHY1LTE2IiwgCiJJZ2h2NS0xNyIsICJJZ2h2Mi05IiwgIklyZjUiLCAiSWdodjctMSIsICJJZ2h2Ny0yIiwgIklnaHYxNC0xIiwgCiJJZ2h2NC0xIiwgIklnaHYzLTEiLCAiSWdodjExLTEiLCAiVHJpbTExIiwgIlNsYSIsICJJZ2h2MTQtMiIsIAoiSWdodjExLTIiLCAiSWdodjE0LTMiLCAiVHJpbTE0IiwgIklnaHYxNi0xIiwgIklnaHY5LTEiLCAiRGh4NTgiLCAKIlRyaW0xMyIsICJQcWJwMSIsICJDeWJhIiwgIklnaHY5LTIiLCAiSWdodjktMyIsICJJZ2h2Ny0zIiwgIkFua2hkMSIsIAoiSWdodjE0LTQiLCAiSWdodjMtMyIsICJPYXNsMiIsICJJZ2h2Ny00IiwgIklnaHYzLTQiLCAiTnJyb3MiLCAKIlRscjEzIiwgIkZlcyIsICJUaWNhbTEiLCAiSWdodjMtNiIsICJJZ2h2OS00IiwgIkFwb2JlYzMiLCAiSWdodjMtOCIsIAoiSWdodjEzLTIiLCAiQW5rcmQxNyIsICJUcmltMTUiLCAiSWdodjEyLTMiLCAiSWdodjYtMyIsICJPYXNsMSIsIAoiVHJpbTEwIiwgIlRscjEiLCAiSWdodjYtNCIsICJDNGJwIiwgIlRyaW01IiwgIlRscjYiLCAiVHJpbTMxIiwgCiJQb2xyM2IiLCAiTWF2cyIsICJWbm4xIiwgIkFwY3MiLCAiQWtpcmluMiIsICJTc2M1ZCIsICJUcmltMTJhIiwgCiJQb2xyM2QiLCAiQ2xlYzVhIiwgIkZnZyIsICJEYWIyaXAiLCAiSG1nYjIiLCAiRmdhIiwgIkZnYiIsICJUcmltMTJjIiwgCiJGZ3IiLCAiSXBvNyIsICJNc3QxciIsICJUcmltMzBiIiwgIlRyaW0zMGMiLCAiU2ZwcSIsICJJbDM0IiwgCiJUcmltMjUiLCAiVHJpbTMwYSIsICJUcmltMzBkIiwgIlBzcGMxIiwgIkNhcmQ5IiwgIk1ibDEiLCAiUHRrMiIsIAoiTGNuMiIsICJBYmwxIiwgIlNmdHBkIiwgIlRscjgiLCAiUHljYXJkIiwgIklnaHY2LTUiLCAiVGxyMiIsIAoiSWdodjYtNiIsICJJZ2h2Ni03IiwgIlNlcnBpbmcxIiwgIlRscjciLCAiU3JjIiwgIklnaHY4LTIiLCAiSWdsYzEiLCAKIklnaHYxMC0xIiwgIklnaHYxLTQiLCAiSWwxZjYiLCAiSWdsYzQiLCAiSWdodjEtNSIsICJJZ2h2MTAtMyIsIAoiSWdodjEtNyIsICJJZ2xjMiIsICJEZWZiMjMiLCAiR3BlcjEiLCAiQ25weTMiLCAiVHJkdjQiLCAiRGVmYjIwIiwgCiJEZWZiMjIiLCAiRGVmYjI2IiwgIkRlZmIyOCIsICJJbDFmNSIsICJEZWZiMjkiLCAiSWdodjE1LTIiLCAKIklnaHYxLTkiLCAiRGVmYjIxIiwgIkl0Y2giLCAiUGdseXJwMSIsICJOZmtiMSIsICJEZWZiMTkiLCAiRGVmYjQ1IiwgCiJJbDFybDIiLCAiRGVmYjM2IiwgIk1pZDIiLCAiRGVmYjI1IiwgIklnaHYxLTExIiwgIklnaHYxLTEyIiwgCiJJZ2h2MS0xNSIsICJJZ2h2MS0xNiIsICJHcmIyIiwgIklnaHYxLTE4IiwgIklnaHYxLTE5IiwgIklnaHYxLTIwIiwgCiJNYXA0azIiLCAiSWwxZjgiLCAiUGlrM2NiIiwgIkFkYW0xNSIsICJJZ2h2MS0yMiIsICJCY2wxMCIsICJJZ2h2MS0yMyIsIAoiSWdodjEtMjQiLCAiSWdodjEtMjYiLCAiUHJrZGMiLCAiSXJhazQiLCAiRjJybDEiLCAiQWRncmIxIiwgCiJJc2cyMCIsICJDMXFiIiwgIkMxcWMiLCAiQzFxYSIsICJNcjEiLCAiUG9scjNhIiwgIlRscjkiLCAiSWdodjEtNzYiLCAKIk9wdG4iLCAiSWdodjEtNzciLCAiUHR4MyIsICJJZ2h2MS03OCIsICJaYnRiMSIsICJHcmFwIiwgIkxicCIsIAoiQXJoZ2VmMiIsICJNY29sbjIiLCAiSWdodjEtODAiLCAiVGJrMSIsICJJZ2h2MS04MSIsICJJZmloMSIsIAoiSWdodjEtMzEiLCAiQm14IiwgIklnaHYxLTgyIiwgIklnaHYxLTM0IiwgIkx5ODYiLCAiTmxyYzUiLCAiSWdodjEtODUiLCAKIlBvbHIzZiIsICJJZ2h2MS0zNiIsICJJZ2h2MS0zNyIsICJUbHIxMSIsICJUcmltMjciLCAiTWFsdDEiLCAKIkZhZGQiLCAiSWdodjEtMzkiLCAiSWdodjEtNDIiLCAiSWdodjEtNDMiLCAiQnRrIiwgIkRjc3QxIiwgIlBhcnAxNCIsIAoiSWdodjEtNDciLCAiSWdodjgtNCIsICJJZ2h2MS00OSIsICJJdGsiLCAiSWdodjgtNSIsICJJZ2h2MS01MCIsIAoiVHJpbTI2IiwgIkNoaWQxIiwgIkNzayIsICJGY2VyMWciLCAiSWdodjEtNTIiLCAiSWdodjEtNTMiLCAiSWdodjgtNiIsIAoiTmFpcDIiLCAiTmxycDMiLCAiQzhnIiwgIklnaHYxLTU0IiwgIkNzZjEiLCAiVHJhZjMiLCAiSWdodjEtNTUiLCAKIklnaHYxLTU2IiwgIkVsZjQiLCAiRHR4M2wiLCAiSXJhazEiLCAiTmFpcDYiLCAiUGFycDkiLCAiSWdodjgtOCIsIAoiSWdodjEtNTgiLCAiUGlrM2NkIiwgIkhjayIsICJJZ2h2MS01OSIsICJDZDE4MCIsICJJcmYzIiwgIklnaHYxLTYxIiwgCiJJZ2h2MS02Mi0xIiwgIklmbmwyIiwgIlJlbGIiLCAiSWZubDMiLCAiRnluIiwgIklnaHYxLTYyLTIiLCAKIklnaHYxLTYyLTMiLCAiSG1nYjEiLCAiVGxyMTIiLCAiSWdodjgtOSIsICJZZXMxIiwgIklnaHYxLTYzIiwgCiJJZ2h2MS02NCIsICJUYmticDEiLCAiU2lnbGVjZyIsICJJZ2h2OC0xMSIsICJJZ2h2MS02NiIsICJDZmgiLCAKIlpjM2hhdjEiLCAiSWdodjEtNjciLCAiSWdodjEtNjkiLCAiSWdodjgtMTIiLCAiSGF2Y3IyIiwgIjQ5MzM0MTVGMjNSaWsiLCAKIlRyaW0zMiIsICJJZ2h2OC0xMyIsICJDMyIsICJJZ2h2MS03NCIsICJUcmltNjIiLCAiSGV4aW0xIiwgIk1hdHIzIiwgCiJJZ2h2MS03NSIsICJTbHBpIiwgIlpmcDgwOSIsICJJZ2xsMSIsICJBcmlkNWEiLCAiVG9sbGlwIiwgIlRscjQiLCAKIlN5ayIsICJDNGIiLCAiQ2QyNDQiLCAiRmJ4bzkiLCAiTHk5IiwgIklmbmIxIiwgIlpmcDY4MyIsICJJZm5hMTUiLCAKIklmbmE5IiwgIklmbmExNCIsICJJZm5hMTIiLCAiTGNrIiwgIlNlcmluYzMiLCAiTmxycDYiLCAiQ2FtcCIsIAoiSWZuYTEzIiwgIklmbmExNiIsICJJZm5hYiIsICJMeW4iLCAiR20xMzI3MSIsICJHbTEzMjgzIiwgIkdtMTMyOTAiLCAKIkdtMTMyODkiLCAiR20xMzI3MiIsICJDZDI0YSIsICJTcG9uMiIsICJMZ3I0IiwgIklmbnoiLCAiR20xMzI3NiIsIAoiR20xMzI3NyIsICJHbTEzMjc4IiwgIlRscjMiLCAiR20xMzI3NSIsICJHbTEzMjc5IiwgIkdtMTMyODUiLCAKIkdtMTMyODciLCAiR20xMzI4OCIsICJJZm5hMTEiLCAiSWZuYTQiLCAiT2FzMiIsICJQcmtkMSIsICJPYXMzIiwgCiJTbGFtZjEiLCAiTWFyY28iLCAiSWZuZSIsICJSYXJyZXMyIiwgIkNsZWM0YTIiLCAiVHJlbWw0IiwgIk9hczFhIiwgCiJTbGFtZjYiLCAiRmNuYSIsICJTYXJtMSIsICJBdGc1IiwgIlRyaW01OSIsICJDbGVjNG4iLCAiSGVyYzYiLCAKIlJpcGsyIiwgIklyZ20xIiwgIlByZG0xIiwgIkhjIiwgIkNsZWM0ZCIsICJDbGVjNGUiLCAiVGljYW0yIiwgCiJUcmVtMiIsICJJbDI3IiwgIkZyayIsICJNaWYiLCAiUHRrMmIiLCAiQzFybCIsICJJcmY3IiwgIkMxcmEiLCAKIkMxcmIiLCAiQzFzMiIsICJQb2xyM2siLCAiWmJwMSIsICJUcmltMzUiLCAiSWwyM2EiLCAiQzIiLCAiQ2ZiIiwgCiJQYWRpNCIsICJDYWN0aW4iLCAiTWFzcDIiLCAiS2xyZzEiLCAiQXJnMiIsICJQdGs2IiwgIkNsZWM3YSIsIAoiUm5mMTM1IiwgIlR4ayIsICJLbHJrMSIsICJTZWMxNGwxIiwgIkNyY3AiLCAiU3R5azEiLCAiVG1lbTE3MyIsIAoiQXRnMTIiLCAiR20xNzQxNiIsICJJaWdwMSIsICJQb2xyM2giLCAiUmlvazMiLCAiQ2QxNCIsICJHbTU4NDkiLCAKIk1ibDIiLCAiQWthcDgiLCAiWHJjYzUiLCAiTmZrYjIiLCAiTWFzcDEiLCAiVHJpbTgiLCAiUGNicDIiLCAKIlBwcDFyMTRiIiwgIkdzZG1kIiwgIkZlciIsICJHcmFwMiIsICJObHJjNCIsICJNYXA0azIiKSwgZXh0ZXJuYWxfZ2VuZV9uYW1lID0gYygiVWJhNyIsIAoiVWJlMmw2IiwgIlViZTJlMSIsICJVYmUyZTIiLCAiSXNnMTUiLCAiSWtia2UiLCAiU2V0ZDIiLCAiQTIzMDA1MFAyMFJpayIsIAoiTXgyIiwgIlNobXQyIiwgIklyZ20yIiwgIkRuYWphMyIsICJLeW51IiwgIkJzdDIiLCAiU2VjNjFhMSIsIAoiQ2l0ZWQxIiwgIkgyLUFhIiwgIlNsYzExYTEiLCAiR2NoMSIsICJVYmQiLCAiSWwyM3IiLCAiU2xjMzBhOCIsIAoiQ3hjbDE2IiwgIkN5cDI3YjEiLCAiVHJpbTIxIiwgIklmaXRtMiIsICJJZml0bTEiLCAiSWZpdG0zIiwgCiJBZGFtdHMxMyIsICJUZ3RwMiIsICJUZ3RwMSIsICJTbmNhIiwgIkNkNDAiLCAiTWVmdiIsICJDaWl0YSIsIAoiS2xobDIwIiwgIkFkYXIiLCAiSWZuYXIyIiwgIkVpZjJhazIiLCAiUGxzY3IxIiwgIkxhbXAzIiwgIlhhZjEiLCAKIlN0YXQxIiwgIlMxMDBhOCIsICJUcmRjIiwgIlMxMDBhOSIsICJBaW0yIiwgIk1iMjFkMSIsICJJcmYxIiwgCiJQZ2x5cnA0IiwgIlNkaGFmNCIsICJEZHgzeCIsICJEZWZiMSIsICJTZXJpbmM1IiwgIkRkeDU4IiwgIkRlZmIxMiIsIAoiRGVmYjM0IiwgIk5scnAxMCIsICJSZWxhIiwgIkdhdGEzIiwgIkNzZjFyIiwgIklnaGEiLCAiRGVmYjE1IiwgCiJSbmFzZTYiLCAiRGVmYjM1IiwgIkRlZmIxMyIsICJQZ2x5cnAzIiwgIklnaGcyYyIsICJLcnQxNiIsICJUcmlsIiwgCiJObHJwOWMiLCAiQnBpZmIzIiwgIlBpazNjYSIsICJObHJwMWEiLCAiTmxycDliIiwgIklnaGczIiwgIklnaGQiLCAKIklnaG0iLCAiTmxycDFiIiwgIkNmaSIsICJMeTk2IiwgIkpjaGFpbiIsICJDOGIiLCAiTmxyeDEiLCAiQ3liYiIsIAoiUG1sIiwgIkM4YSIsICJUbmsxIiwgIlBvbHIzYyIsICJJbDFyYXAiLCAiUmJtMTQiLCAiUG9scjNlIiwgCiJBbnhhMSIsICJDZmQiLCAiSWZuayIsICJGY25iIiwgIk5yMWg0IiwgIkRlZmI0MyIsICJOb25vIiwgIjU3MzA1NTlDMThSaWsiLCAKIkhtZ2IzIiwgIkRlZmIzMCIsICJTaDJkMWIyIiwgIklnaHY1LTIiLCAiSWdodjItMiIsICJUbmZhaXA4bDIiLCAKIlRhcm0xIiwgIklnaHY1LTQiLCAiQnBpZmExIiwgIk5vZDIiLCAiSWdodjItMyIsICJPdHVsaW4iLCAiSWdodjUtNiIsIAoiQnBpZmIxIiwgIklmaTIwMmIiLCAiSWdodjUtOSIsICJGY2dyMSIsICJUcmltMjgiLCAiQXJnMSIsICJUcmJjMSIsIAoiUGlrM2NnIiwgIkRlZmIxOCIsICJEZWZiNDEiLCAiSWdodjItNSIsICJJZ2h2NS0xMiIsICJJZ2h2Mi02IiwgCiJJZ2h2NS05LTEiLCAiUG9scjNnIiwgIkN5bGQiLCAiU2gyZDFhIiwgIlphcDcwIiwgIklmaXQzIiwgIlJzYWQyIiwgCiJNc3JiMSIsICJJZml0MSIsICJDcjFsIiwgIkNmcCIsICJTcDExMCIsICJUcmJjMiIsICJDYXNwNCIsICJOb2QxIiwgCiJTbGEyIiwgIlNtcGRsM2IiLCAiVGxyNSIsICJJZ2h2NS0xMi00IiwgIklnaHYyLTktMSIsICJBeGwiLCAKIk1hcDNrNSIsICJDZDU1IiwgIkJsayIsICJNeWQ4OCIsICJUbmZzZjQiLCAiSWdodjItNi04IiwgIklnaHYyLTciLCAKIklnaHY1LTE1IiwgIklnaHY1LTE2IiwgIklnaHY1LTE3IiwgIklnaHYyLTkiLCAiSXJmNSIsICJJZ2h2Ny0xIiwgCiJJZ2h2Ny0yIiwgIklnaHYxNC0xIiwgIklnaHY0LTEiLCAiSWdodjMtMSIsICJJZ2h2MTEtMSIsICJUcmltMTEiLCAKIlNsYSIsICJJZ2h2MTQtMiIsICJJZ2h2MTEtMiIsICJJZ2h2MTQtMyIsICJUcmltMTQiLCAiSWdodjE2LTEiLCAKIklnaHY5LTEiLCAiRGh4NTgiLCAiVHJpbTEzIiwgIlBxYnAxIiwgIkN5YmEiLCAiSWdodjktMiIsICJJZ2h2OS0zIiwgCiJJZ2h2Ny0zIiwgIkFua2hkMSIsICJJZ2h2MTQtNCIsICJJZ2h2My0zIiwgIk9hc2wyIiwgIklnaHY3LTQiLCAKIklnaHYzLTQiLCAiTnJyb3MiLCAiVGxyMTMiLCAiRmVzIiwgIlRpY2FtMSIsICJJZ2h2My02IiwgIklnaHY5LTQiLCAKIkFwb2JlYzMiLCAiSWdodjMtOCIsICJJZ2h2MTMtMiIsICJBbmtyZDE3IiwgIlRyaW0xNSIsICJJZ2h2MTItMyIsIAoiSWdodjYtMyIsICJPYXNsMSIsICJUcmltMTAiLCAiVGxyMSIsICJJZ2h2Ni00IiwgIkM0YnAiLCAiVHJpbTUiLCAKIlRscjYiLCAiVHJpbTMxIiwgIlBvbHIzYiIsICJNYXZzIiwgIlZubjEiLCAiQXBjcyIsICJBa2lyaW4yIiwgCiJTc2M1ZCIsICJUcmltMTJhIiwgIlBvbHIzZCIsICJDbGVjNWEiLCAiRmdnIiwgIkRhYjJpcCIsICJIbWdiMiIsIAoiRmdhIiwgIkZnYiIsICJUcmltMTJjIiwgIkZnciIsICJJcG83IiwgIk1zdDFyIiwgIlRyaW0zMGIiLCAiVHJpbTMwYyIsIAoiU2ZwcSIsICJJbDM0IiwgIlRyaW0yNSIsICJUcmltMzBhIiwgIlRyaW0zMGQiLCAiUHNwYzEiLCAiQ2FyZDkiLCAKIk1ibDEiLCAiUHRrMiIsICJMY24yIiwgIkFibDEiLCAiU2Z0cGQiLCAiVGxyOCIsICJQeWNhcmQiLCAiSWdodjYtNSIsIAoiVGxyMiIsICJJZ2h2Ni02IiwgIklnaHY2LTciLCAiU2VycGluZzEiLCAiVGxyNyIsICJTcmMiLCAiSWdodjgtMiIsIAoiSWdsYzEiLCAiSWdodjEwLTEiLCAiSWdodjEtNCIsICJJbDFmNiIsICJJZ2xjNCIsICJJZ2h2MS01IiwgCiJJZ2h2MTAtMyIsICJJZ2h2MS03IiwgIklnbGMyIiwgIkRlZmIyMyIsICJHcGVyMSIsICJDbnB5MyIsICJUcmR2NCIsIAoiRGVmYjIwIiwgIkRlZmIyMiIsICJEZWZiMjYiLCAiRGVmYjI4IiwgIklsMWY1IiwgIkRlZmIyOSIsICJJZ2h2MTUtMiIsIAoiSWdodjEtOSIsICJEZWZiMjEiLCAiSXRjaCIsICJQZ2x5cnAxIiwgIk5ma2IxIiwgIkRlZmIxOSIsICJEZWZiNDUiLCAKIklsMXJsMiIsICJEZWZiMzYiLCAiTWlkMiIsICJEZWZiMjUiLCAiSWdodjEtMTEiLCAiSWdodjEtMTIiLCAKIklnaHYxLTE1IiwgIklnaHYxLTE2IiwgIkdyYjIiLCAiSWdodjEtMTgiLCAiSWdodjEtMTkiLCAiSWdodjEtMjAiLCAKIk1hcDRrMiIsICJJbDFmOCIsICJQaWszY2IiLCAiQWRhbTE1IiwgIklnaHYxLTIyIiwgIkJjbDEwIiwgIklnaHYxLTIzIiwgCiJJZ2h2MS0yNCIsICJJZ2h2MS0yNiIsICJQcmtkYyIsICJJcmFrNCIsICJGMnJsMSIsICJBZGdyYjEiLCAKIklzZzIwIiwgIkMxcWIiLCAiQzFxYyIsICJDMXFhIiwgIk1yMSIsICJQb2xyM2EiLCAiVGxyOSIsICJJZ2h2MS03NiIsIAoiT3B0biIsICJJZ2h2MS03NyIsICJQdHgzIiwgIklnaHYxLTc4IiwgIlpidGIxIiwgIkdyYXAiLCAiTGJwIiwgCiJBcmhnZWYyIiwgIk1jb2xuMiIsICJJZ2h2MS04MCIsICJUYmsxIiwgIklnaHYxLTgxIiwgIklmaWgxIiwgCiJJZ2h2MS0zMSIsICJCbXgiLCAiSWdodjEtODIiLCAiSWdodjEtMzQiLCAiTHk4NiIsICJObHJjNSIsICJJZ2h2MS04NSIsIAoiUG9scjNmIiwgIklnaHYxLTM2IiwgIklnaHYxLTM3IiwgIlRscjExIiwgIlRyaW0yNyIsICJNYWx0MSIsIAoiRmFkZCIsICJJZ2h2MS0zOSIsICJJZ2h2MS00MiIsICJJZ2h2MS00MyIsICJCdGsiLCAiRGNzdDEiLCAiUGFycDE0IiwgCiJJZ2h2MS00NyIsICJJZ2h2OC00IiwgIklnaHYxLTQ5IiwgIkl0ayIsICJJZ2h2OC01IiwgIklnaHYxLTUwIiwgCiJUcmltMjYiLCAiQ2hpZDEiLCAiQ3NrIiwgIkZjZXIxZyIsICJJZ2h2MS01MiIsICJJZ2h2MS01MyIsICJJZ2h2OC02IiwgCiJOYWlwMiIsICJObHJwMyIsICJDOGciLCAiSWdodjEtNTQiLCAiQ3NmMSIsICJUcmFmMyIsICJJZ2h2MS01NSIsIAoiSWdodjEtNTYiLCAiRWxmNCIsICJEdHgzbCIsICJJcmFrMSIsICJOYWlwNiIsICJQYXJwOSIsICJJZ2h2OC04IiwgCiJJZ2h2MS01OCIsICJQaWszY2QiLCAiSGNrIiwgIklnaHYxLTU5IiwgIkNkMTgwIiwgIklyZjMiLCAiSWdodjEtNjEiLCAKIklnaHYxLTYyLTEiLCAiSWZubDIiLCAiUmVsYiIsICJJZm5sMyIsICJGeW4iLCAiSWdodjEtNjItMiIsIAoiSWdodjEtNjItMyIsICJIbWdiMSIsICJUbHIxMiIsICJJZ2h2OC05IiwgIlllczEiLCAiSWdodjEtNjMiLCAKIklnaHYxLTY0IiwgIlRia2JwMSIsICJTaWdsZWNnIiwgIklnaHY4LTExIiwgIklnaHYxLTY2IiwgIkNmaCIsIAoiWmMzaGF2MSIsICJJZ2h2MS02NyIsICJJZ2h2MS02OSIsICJJZ2h2OC0xMiIsICJIYXZjcjIiLCAiNDkzMzQxNUYyM1JpayIsIAoiVHJpbTMyIiwgIklnaHY4LTEzIiwgIkMzIiwgIklnaHYxLTc0IiwgIlRyaW02MiIsICJIZXhpbTEiLCAiTWF0cjMiLCAKIklnaHYxLTc1IiwgIlNscGkiLCAiWmZwODA5IiwgIklnbGwxIiwgIkFyaWQ1YSIsICJUb2xsaXAiLCAiVGxyNCIsIAoiU3lrIiwgIkM0YiIsICJDZDI0NCIsICJGYnhvOSIsICJMeTkiLCAiSWZuYjEiLCAiWmZwNjgzIiwgIklmbmExNSIsIAoiSWZuYTkiLCAiSWZuYTE0IiwgIklmbmExMiIsICJMY2siLCAiU2VyaW5jMyIsICJObHJwNiIsICJDYW1wIiwgCiJJZm5hMTMiLCAiSWZuYTE2IiwgIklmbmFiIiwgIkx5biIsICJHbTEzMjcxIiwgIkdtMTMyODMiLCAiR20xMzI5MCIsIAoiR20xMzI4OSIsICJHbTEzMjcyIiwgIkNkMjRhIiwgIlNwb24yIiwgIkxncjQiLCAiSWZueiIsICJHbTEzMjc2IiwgCiJHbTEzMjc3IiwgIkdtMTMyNzgiLCAiVGxyMyIsICJHbTEzMjc1IiwgIkdtMTMyNzkiLCAiR20xMzI4NSIsIAoiR20xMzI4NyIsICJHbTEzMjg4IiwgIklmbmExMSIsICJJZm5hNCIsICJPYXMyIiwgIlBya2QxIiwgIk9hczMiLCAKIlNsYW1mMSIsICJNYXJjbyIsICJJZm5lIiwgIlJhcnJlczIiLCAiQ2xlYzRhMiIsICJUcmVtbDQiLCAiT2FzMWEiLCAKIlNsYW1mNiIsICJGY25hIiwgIlNhcm0xIiwgIkF0ZzUiLCAiVHJpbTU5IiwgIkNsZWM0biIsICJIZXJjNiIsIAoiUmlwazIiLCAiSXJnbTEiLCAiUHJkbTEiLCAiSGMiLCAiQ2xlYzRkIiwgIkNsZWM0ZSIsICJUaWNhbTIiLCAKIlRyZW0yIiwgIklsMjciLCAiRnJrIiwgIk1pZiIsICJQdGsyYiIsICJDMXJsIiwgIklyZjciLCAiQzFyYSIsIAoiQzFyYiIsICJDMXMyIiwgIlBvbHIzayIsICJaYnAxIiwgIlRyaW0zNSIsICJJbDIzYSIsICJDMiIsICJDZmIiLCAKIlBhZGk0IiwgIkNhY3RpbiIsICJNYXNwMiIsICJLbHJnMSIsICJBcmcyIiwgIlB0azYiLCAiQ2xlYzdhIiwgCiJSbmYxMzUiLCAiVHhrIiwgIktscmsxIiwgIlNlYzE0bDEiLCAiQ3JjcCIsICJTdHlrMSIsICJUbWVtMTczIiwgCiJBdGcxMiIsICJHbTE3NDE2IiwgIklpZ3AxIiwgIlBvbHIzaCIsICJSaW9rMyIsICJDZDE0IiwgIkdtNTg0OSIsIAoiTWJsMiIsICJBa2FwOCIsICJYcmNjNSIsICJOZmtiMiIsICJNYXNwMSIsICJUcmltOCIsICJQY2JwMiIsIAoiUHBwMXIxNGIiLCAiR3NkbWQiLCAiRmVyIiwgIkdyYXAyIiwgIk5scmM0IiwgIk1hcDRrMiIpLCBlbnNlbWJsX2dlbmVfaWQgPSBjKCJFTlNNVVNHMDAwMDAwMzI1OTYiLCAKIkVOU01VU0cwMDAwMDAyNzA3OCIsICJFTlNNVVNHMDAwMDAwMjE3NzQiLCAiRU5TTVVTRzAwMDAwMDU4MzE3IiwgCiJFTlNNVVNHMDAwMDAwMzU2OTIiLCAiRU5TTVVTRzAwMDAwMDQyMzQ5IiwgIkVOU01VU0cwMDAwMDA0NDc5MSIsIAoiRU5TTVVTRzAwMDAwMDM4ODg0IiwgIkVOU01VU0cwMDAwMDAyMzM0MSIsICJFTlNNVVNHMDAwMDAwMjU0MDMiLCAKIkVOU01VU0cwMDAwMDA2OTg3NCIsICJFTlNNVVNHMDAwMDAwMDQwNjkiLCAiRU5TTVVTRzAwMDAwMDI2ODY2IiwgCiJFTlNNVVNHMDAwMDAwNDY3MTgiLCAiRU5TTVVTRzAwMDAwMDMwMDgyIiwgIkVOU01VU0cwMDAwMDA1MTE1OSIsIAoiRU5TTVVTRzAwMDAwMDM2NTk0IiwgIkVOU01VU0cwMDAwMDAyNjE3NyIsICJFTlNNVVNHMDAwMDAwMzc1ODAiLCAKIkVOU01VU0cwMDAwMDAzNTE4NiIsICJFTlNNVVNHMDAwMDAwNDkwOTMiLCAiRU5TTVVTRzAwMDAwMDIyMzE1IiwgCiJFTlNNVVNHMDAwMDAwMTg5MjAiLCAiRU5TTVVTRzAwMDAwMDA2NzI0IiwgIkVOU01VU0cwMDAwMDAzMDk2NiIsIAoiRU5TTVVTRzAwMDAwMDYwNTkxIiwgIkVOU01VU0cwMDAwMDAyNTQ5MSIsICJFTlNNVVNHMDAwMDAwMjU0OTIiLCAKIkVOU01VU0cwMDAwMDAxNDg1MiIsICJFTlNNVVNHMDAwMDAwNzg5MjEiLCAiRU5TTVVTRzAwMDAwMDc4OTIyIiwgCiJFTlNNVVNHMDAwMDAwMjU4ODkiLCAiRU5TTVVTRzAwMDAwMDE3NjUyIiwgIkVOU01VU0cwMDAwMDAyMjUzNCIsIAoiRU5TTVVTRzAwMDAwMDIyNTA0IiwgIkVOU01VU0cwMDAwMDAyNjcwNSIsICJFTlNNVVNHMDAwMDAwMjc5NTEiLCAKIkVOU01VU0cwMDAwMDAyMjk3MSIsICJFTlNNVVNHMDAwMDAwMjQwNzkiLCAiRU5TTVVTRzAwMDAwMDMyMzY5IiwgCiJFTlNNVVNHMDAwMDAwNDEyNDciLCAiRU5TTVVTRzAwMDAwMDQwNDgzIiwgIkVOU01VU0cwMDAwMDAyNjEwNCIsIAoiRU5TTVVTRzAwMDAwMDU2MDU0IiwgIkVOU01VU0cwMDAwMDEwNDg3NiIsICJFTlNNVVNHMDAwMDAwNTYwNzEiLCAKIkVOU01VU0cwMDAwMDAzNzg2MCIsICJFTlNNVVNHMDAwMDAwMzIzNDQiLCAiRU5TTVVTRzAwMDAwMDE4ODk5IiwgCiJFTlNNVVNHMDAwMDAwNDIyNTAiLCAiRU5TTVVTRzAwMDAwMDI2MTU0IiwgIkVOU01VU0cwMDAwMDAwMDc4NyIsIAoiRU5TTVVTRzAwMDAwMDQ0NzQ4IiwgIkVOU01VU0cwMDAwMDAyMTcwMyIsICJFTlNNVVNHMDAwMDAwNDAyOTYiLCAKIkVOU01VU0cwMDAwMDA0Mzc4NyIsICJFTlNNVVNHMDAwMDAwNTI1NTQiLCAiRU5TTVVTRzAwMDAwMDQ5NzA5IiwgCiJFTlNNVVNHMDAwMDAwMjQ5MjciLCAiRU5TTVVTRzAwMDAwMDE1NjE5IiwgIkVOU01VU0cwMDAwMDAyNDYyMSIsIAoiRU5TTVVTRzAwMDAwMDk1MDc5IiwgIkVOU01VU0cwMDAwMDA0ODUwMCIsICJFTlNNVVNHMDAwMDAwMjE4ODAiLCAKIkVOU01VU0cwMDAwMDA1ODA1MiIsICJFTlNNVVNHMDAwMDAwNDQyMjIiLCAiRU5TTVVTRzAwMDAwMDQyMjQ0IiwgCiJFTlNNVVNHMDAwMDAwNzY2MTIiLCAiRU5TTVVTRzAwMDAwMDUzNzk3IiwgIkVOU01VU0cwMDAwMDA0MzQ5NiIsIAoiRU5TTVVTRzAwMDAwMDQwNjE0IiwgIkVOU01VU0cwMDAwMDA2ODAwOCIsICJFTlNNVVNHMDAwMDAwMjc2NjUiLCAKIkVOU01VU0cwMDAwMDA2OTgzMCIsICJFTlNNVVNHMDAwMDAwNjA1MDgiLCAiRU5TTVVTRzAwMDAwMDc2NjE1IiwgCiJFTlNNVVNHMDAwMDAxMDQyMTMiLCAiRU5TTVVTRzAwMDAwMDc2NjE3IiwgIkVOU01VU0cwMDAwMDA3MDM5MCIsIAoiRU5TTVVTRzAwMDAwMDU4OTUyIiwgIkVOU01VU0cwMDAwMDAyNTc3OSIsICJFTlNNVVNHMDAwMDAwNjcxNDkiLCAKIkVOU01VU0cwMDAwMDAyOTY1NiIsICJFTlNNVVNHMDAwMDAwMzIxMDkiLCAiRU5TTVVTRzAwMDAwMDE1MzQwIiwgCiJFTlNNVVNHMDAwMDAwMzY5ODYiLCAiRU5TTVVTRzAwMDAwMDM1MDMxIiwgIkVOU01VU0cwMDAwMDAwMTU4MyIsIAoiRU5TTVVTRzAwMDAwMDI4MDk5IiwgIkVOU01VU0cwMDAwMDAyMjUxNCIsICJFTlNNVVNHMDAwMDAwMDY0NTYiLCAKIkVOU01VU0cwMDAwMDAzMDg4MCIsICJFTlNNVVNHMDAwMDAwMjQ2NTkiLCAiRU5TTVVTRzAwMDAwMDYxNzgwIiwgCiJFTlNNVVNHMDAwMDAwNDI5OTMiLCAiRU5TTVVTRzAwMDAwMDI2ODM1IiwgIkVOU01VU0cwMDAwMDA0NzYzOCIsIAoiRU5TTVVTRzAwMDAwMDc1NTcyIiwgIkVOU01VU0cwMDAwMDAzMTMxMSIsICJFTlNNVVNHMDAwMDAwNDE2MDUiLCAKIkVOU01VU0cwMDAwMDAxNTIxNyIsICJFTlNNVVNHMDAwMDAwNzU1NzEiLCAiRU5TTVVTRzAwMDAwMDczNDk0IiwgCiJFTlNNVVNHMDAwMDAwNzY2MzMiLCAiRU5TTVVTRzAwMDAwMDk2NDY0IiwgIkVOU01VU0cwMDAwMDAxMzcwNyIsIAoiRU5TTVVTRzAwMDAwMDUzMzM4IiwgIkVOU01VU0cwMDAwMDA5NTYxMiIsICJFTlNNVVNHMDAwMDAwMjc0ODMiLCAKIkVOU01VU0cwMDAwMDA1NTk5NCIsICJFTlNNVVNHMDAwMDAwOTQxNjQiLCAiRU5TTVVTRzAwMDAwMDQ2MDM0IiwgCiJFTlNNVVNHMDAwMDAwOTQ5NTEiLCAiRU5TTVVTRzAwMDAwMDI3NDg1IiwgIkVOU01VU0cwMDAwMDAyNjUzNSIsIAoiRU5TTVVTRzAwMDAwMDk1Mjg1IiwgIkVOU01VU0cwMDAwMDAxNTk0NyIsICJFTlNNVVNHMDAwMDAwMDU1NjYiLCAKIkVOU01VU0cwMDAwMDAxOTk4NyIsICJFTlNNVVNHMDAwMDAwNzY0OTAiLCAiRU5TTVVTRzAwMDAwMDIwNTczIiwgCiJFTlNNVVNHMDAwMDAwNzM3MzUiLCAiRU5TTVVTRzAwMDAwMDY3NzczIiwgIkVOU01VU0cwMDAwMDA5NjQ5OCIsIAoiRU5TTVVTRzAwMDAwMDk1NDI5IiwgIkVOU01VU0cwMDAwMDA5NjY3MCIsICJFTlNNVVNHMDAwMDAwOTUyMTAiLCAKIkVOU01VU0cwMDAwMDAzNTgzNCIsICJFTlNNVVNHMDAwMDAwMzY3MTIiLCAiRU5TTVVTRzAwMDAwMDA1Njk2IiwgCiJFTlNNVVNHMDAwMDAwMjYxMTciLCAiRU5TTVVTRzAwMDAwMDc0ODk2IiwgIkVOU01VU0cwMDAwMDAyMDY0MSIsIAoiRU5TTVVTRzAwMDAwMDc1NzA1IiwgIkVOU01VU0cwMDAwMDAzNDQ1OSIsICJFTlNNVVNHMDAwMDAwMTY0ODEiLCAKIkVOU01VU0cwMDAwMDAwMTEyOCIsICJFTlNNVVNHMDAwMDAwNzAwMzQiLCAiRU5TTVVTRzAwMDAwMDc2NDk4IiwgCiJFTlNNVVNHMDAwMDAwMzM1MzgiLCAiRU5TTVVTRzAwMDAwMDM4MDU4IiwgIkVOU01VU0cwMDAwMDAyNzYzNiIsIAoiRU5TTVVTRzAwMDAwMDI4ODg1IiwgIkVOU01VU0cwMDAwMDA3OTE2NCIsICJFTlNNVVNHMDAwMDAxMDMwMzMiLCAKIkVOU01VU0cwMDAwMDA5NTU2NSIsICJFTlNNVVNHMDAwMDAwMDI2MDIiLCAiRU5TTVVTRzAwMDAwMDcxMzY5IiwgCiJFTlNNVVNHMDAwMDAwMjYzOTkiLCAiRU5TTVVTRzAwMDAwMDE0NDUzIiwgIkVOU01VU0cwMDAwMDAzMjUwOCIsIAoiRU5TTVVTRzAwMDAwMDI2NzAwIiwgIkVOU01VU0cwMDAwMDA3NjY0NiIsICJFTlNNVVNHMDAwMDAwOTY4MjQiLCAKIkVOU01VU0cwMDAwMDA5NDEzNCIsICJFTlNNVVNHMDAwMDAwOTQxOTQiLCAiRU5TTVVTRzAwMDAwMDk1NTcxIiwgCiJFTlNNVVNHMDAwMDAwOTY2MzgiLCAiRU5TTVVTRzAwMDAwMDI5NzcxIiwgIkVOU01VU0cwMDAwMDA3NjY2NSIsIAoiRU5TTVVTRzAwMDAwMDc2NjUzIiwgIkVOU01VU0cwMDAwMDA5NDUwOSIsICJFTlNNVVNHMDAwMDAwNzY2NTUiLCAKIkVOU01VU0cwMDAwMDA5MzgzOCIsICJFTlNNVVNHMDAwMDAwOTQ1MzMiLCAiRU5TTVVTRzAwMDAwMDIwNDU1IiwgCiJFTlNNVVNHMDAwMDAwMjIzNzIiLCAiRU5TTVVTRzAwMDAwMDk1NTgzIiwgIkVOU01VU0cwMDAwMDA5NjEwOCIsIAoiRU5TTVVTRzAwMDAwMDk1NjQyIiwgIkVOU01VU0cwMDAwMDAzOTg1MyIsICJFTlNNVVNHMDAwMDAwNzY2NjEiLCAKIkVOU01VU0cwMDAwMDA5NjgwNSIsICJFTlNNVVNHMDAwMDAwMTc4MzAiLCAiRU5TTVVTRzAwMDAwMDM1MjM1IiwgCiJFTlNNVVNHMDAwMDAwMzExNTciLCAiRU5TTVVTRzAwMDAwMDA2NTE5IiwgIkVOU01VU0cwMDAwMDA5NDEwMiIsIAoiRU5TTVVTRzAwMDAwMDk2NDU5IiwgIkVOU01VU0cwMDAwMDA3NjY1MiIsICJFTlNNVVNHMDAwMDAwMjQ0ODMiLCAKIkVOU01VU0cwMDAwMDA3NjY2NiIsICJFTlNNVVNHMDAwMDAwOTQwMjkiLCAiRU5TTVVTRzAwMDAwMDI5NTYxIiwgCiJFTlNNVVNHMDAwMDAwNzY2NjgiLCAiRU5TTVVTRzAwMDAwMTAzOTM5IiwgIkVOU01VU0cwMDAwMDA1MjM4NCIsIAoiRU5TTVVTRzAwMDAwMDMzNzc3IiwgIkVOU01VU0cwMDAwMDA1MzE1OCIsICJFTlNNVVNHMDAwMDAwNDcxMjMiLCAKIkVOU01VU0cwMDAwMDA3NjY3MiIsICJFTlNNVVNHMDAwMDAwOTQzMjIiLCAiRU5TTVVTRzAwMDAwMDA5NTg1IiwgCiJFTlNNVVNHMDAwMDAwNzY2NzQiLCAiRU5TTVVTRzAwMDAwMDc2NjcxIiwgIkVOU01VU0cwMDAwMDA1NTIwNCIsIAoiRU5TTVVTRzAwMDAwMDUwNzQ3IiwgIkVOU01VU0cwMDAwMDA3NjY3NiIsICJFTlNNVVNHMDAwMDAwNzY2NzciLCAKIkVOU01VU0cwMDAwMDA0MTgyNyIsICJFTlNNVVNHMDAwMDAwNzM0MDAiLCAiRU5TTVVTRzAwMDAwMDQ0ODI3IiwgCiJFTlNNVVNHMDAwMDAwOTQxNzQiLCAiRU5TTVVTRzAwMDAwMDI2NDA1IiwgIkVOU01VU0cwMDAwMDA2MDQ0MSIsIAoiRU5TTVVTRzAwMDAwMDUxNDk4IiwgIkVOU01VU0cwMDAwMDA1ODA2MyIsICJFTlNNVVNHMDAwMDAwMzQ0NTMiLCAKIkVOU01VU0cwMDAwMDAzNzUyMyIsICJFTlNNVVNHMDAwMDAwMzc0NDAiLCAiRU5TTVVTRzAwMDAwMDI2NTQyIiwgCiJFTlNNVVNHMDAwMDAwMjgyOTEiLCAiRU5TTVVTRzAwMDAwMDM1Mjc5IiwgIkVOU01VU0cwMDAwMDA2NjI1OCIsIAoiRU5TTVVTRzAwMDAwMDAwNzc2IiwgIkVOU01VU0cwMDAwMDAyOTkxNSIsICJFTlNNVVNHMDAwMDAwMzM4NjAiLCAKIkVOU01VU0cwMDAwMDAyNjg4MyIsICJFTlNNVVNHMDAwMDAwNTQ3MTciLCAiRU5TTVVTRzAwMDAwMDI4MDAxIiwgCiJFTlNNVVNHMDAwMDAwMzM4MzEiLCAiRU5TTVVTRzAwMDAwMDU3MTQzIiwgIkVOU01VU0cwMDAwMDAyODg3NCIsIAoiRU5TTVVTRzAwMDAwMDY2MjMyIiwgIkVOU01VU0cwMDAwMDAzMjU4NCIsICJFTlNNVVNHMDAwMDAwNTI3NDkiLCAKIkVOU01VU0cwMDAwMDA3ODYxNiIsICJFTlNNVVNHMDAwMDAwMjg4MjAiLCAiRU5TTVVTRzAwMDAwMDMxNzUwIiwgCiJFTlNNVVNHMDAwMDAwMDAyNzUiLCAiRU5TTVVTRzAwMDAwMDMwOTIxIiwgIkVOU01VU0cwMDAwMDA1NzU5NiIsIAoiRU5TTVVTRzAwMDAwMDIxOTM4IiwgIkVOU01VU0cwMDAwMDAyNjkyOCIsICJFTlNNVVNHMDAwMDAwMzc3ODAiLCAKIkVOU01VU0cwMDAwMDAyMjYwNyIsICJFTlNNVVNHMDAwMDAwMjY4MjIiLCAiRU5TTVVTRzAwMDAwMDI2ODQyIiwgCiJFTlNNVVNHMDAwMDAwMjE3OTUiLCAiRU5TTVVTRzAwMDAwMDQwNTIyIiwgIkVOU01VU0cwMDAwMDAzMDc5MyIsIAoiRU5TTVVTRzAwMDAwMDk2NDA3IiwgIkVOU01VU0cwMDAwMDAyNzk5NSIsICJFTlNNVVNHMDAwMDAwNzY2ODAiLCAKIkVOU01VU0cwMDAwMDA4NzU4MiIsICJFTlNNVVNHMDAwMDAwMjMyMjQiLCAiRU5TTVVTRzAwMDAwMDQ0NTgzIiwgCiJFTlNNVVNHMDAwMDAwMjc2NDYiLCAiRU5TTVVTRzAwMDAwMTAyMzAxIiwgIkVOU01VU0cwMDAwMDEwNTkwNiIsIAoiRU5TTVVTRzAwMDAwMDk1OTgxIiwgIkVOU01VU0cwMDAwMDA5NTQ0MiIsICJFTlNNVVNHMDAwMDAwMjY5ODQiLCAKIkVOU01VU0cwMDAwMDEwNjAzOSIsICJFTlNNVVNHMDAwMDAwOTY0OTkiLCAiRU5TTVVTRzAwMDAwMDk1NzAwIiwgCiJFTlNNVVNHMDAwMDAwOTUyMDAiLCAiRU5TTVVTRzAwMDAwMDc2OTM3IiwgIkVOU01VU0cwMDAwMDA3NDY4MSIsIAoiRU5TTVVTRzAwMDAwMDUzNjQ3IiwgIkVOU01VU0cwMDAwMDAyMzk3MyIsICJFTlNNVVNHMDAwMDAwNzY4NjciLCAKIkVOU01VU0cwMDAwMDA0OTU2MCIsICJFTlNNVVNHMDAwMDAwMjc0NjgiLCAiRU5TTVVTRzAwMDAwMDc0NjgwIiwgCiJFTlNNVVNHMDAwMDAwNzQ2NzkiLCAiRU5TTVVTRzAwMDAwMDI2OTgzIiwgIkVOU01VU0cwMDAwMDA0NDI0OSIsIAoiRU5TTVVTRzAwMDAwMDc2Njg4IiwgIkVOU01VU0cwMDAwMDA5NDY5NCIsICJFTlNNVVNHMDAwMDAwNTY1NDQiLCAKIkVOU01VU0cwMDAwMDAyNzU5OCIsICJFTlNNVVNHMDAwMDAwMzA0MTMiLCAiRU5TTVVTRzAwMDAwMDI4MTYzIiwgCiJFTlNNVVNHMDAwMDAwNTA2NDUiLCAiRU5TTVVTRzAwMDAwMDYyMTI0IiwgIkVOU01VU0cwMDAwMDA3MDk0MiIsIAoiRU5TTVVTRzAwMDAwMDQ0ODYzIiwgIkVOU01VU0cwMDAwMDAwMDI2NiIsICJFTlNNVVNHMDAwMDAwNzQ2NzgiLCAKIkVOU01VU0cwMDAwMDEwMjg4OCIsICJFTlNNVVNHMDAwMDAwOTU0MTYiLCAiRU5TTVVTRzAwMDAwMTAzMjU0IiwgCiJFTlNNVVNHMDAwMDAwOTU1NTQiLCAiRU5TTVVTRzAwMDAwMDU5OTIzIiwgIkVOU01VU0cwMDAwMDA3NjY5NSIsIAoiRU5TTVVTRzAwMDAwMDk2NDEwIiwgIkVOU01VU0cwMDAwMDA5NTc2MSIsICJFTlNNVVNHMDAwMDAwMjQ5NDgiLCAKIkVOU01VU0cwMDAwMDAyNjk4NSIsICJFTlNNVVNHMDAwMDAwMzI0NjIiLCAiRU5TTVVTRzAwMDAwMDI4MDQxIiwgCiJFTlNNVVNHMDAwMDAwOTQ1NjEiLCAiRU5TTVVTRzAwMDAwMDI4MTkxIiwgIkVOU01VU0cwMDAwMDEwMzI5MCIsIAoiRU5TTVVTRzAwMDAwMDk0MjQxIiwgIkVOU01VU0cwMDAwMDA5NDU0NiIsICJFTlNNVVNHMDAwMDAwMjI2NzIiLCAKIkVOU01VU0cwMDAwMDA1OTg4MyIsICJFTlNNVVNHMDAwMDAwMjE2NzgiLCAiRU5TTVVTRzAwMDAwMDM0NzMwIiwgCiJFTlNNVVNHMDAwMDAwMzkyMzYiLCAiRU5TTVVTRzAwMDAwMDM2OTA1IiwgIkVOU01VU0cwMDAwMDAzNjg5NiIsIAoiRU5TTVVTRzAwMDAwMDM2ODg3IiwgIkVOU01VU0cwMDAwMDAyNjQ3MSIsICJFTlNNVVNHMDAwMDAwMjUyODAiLCAKIkVOU01VU0cwMDAwMDA0NTMyMiIsICJFTlNNVVNHMDAwMDAwOTM4OTYiLCAiRU5TTVVTRzAwMDAwMDI2NjcyIiwgCiJFTlNNVVNHMDAwMDAwOTY0NTIiLCAiRU5TTVVTRzAwMDAwMDI3ODMyIiwgIkVOU01VU0cwMDAwMDA5NjMyNiIsIAoiRU5TTVVTRzAwMDAwMDMzNDU0IiwgIkVOU01VU0cwMDAwMDAwNDgzNyIsICJFTlNNVVNHMDAwMDAwMTYwMjQiLCAKIkVOU01VU0cwMDAwMDAyODA1OSIsICJFTlNNVVNHMDAwMDAwMTEwMDgiLCAiRU5TTVVTRzAwMDAwMDk0MDc1IiwgCiJFTlNNVVNHMDAwMDAwMjAxMTUiLCAiRU5TTVVTRzAwMDAwMDk0Njg5IiwgIkVOU01VU0cwMDAwMDAyNjg5NiIsIAoiRU5TTVVTRzAwMDAwMDk2NjQ5IiwgIkVOU01VU0cwMDAwMDAzMTM3NyIsICJFTlNNVVNHMDAwMDAwOTUxMjciLCAKIkVOU01VU0cwMDAwMDA5Mzk1NSIsICJFTlNNVVNHMDAwMDAwMjE0MjMiLCAiRU5TTVVTRzAwMDAwMDc0MTUxIiwgCiJFTlNNVVNHMDAwMDAwOTYxNTAiLCAiRU5TTVVTRzAwMDAwMDI3NDI3IiwgIkVOU01VU0cwMDAwMDA5NDA1MSIsIAoiRU5TTVVTRzAwMDAwMDk1OTIzIiwgIkVOU01VU0cwMDAwMDA1MTk2OSIsICJFTlNNVVNHMDAwMDAwMjEzMjYiLCAKIkVOU01VU0cwMDAwMDAzMjY4OCIsICJFTlNNVVNHMDAwMDAwMzEwNzciLCAiRU5TTVVTRzAwMDAwMDk1MTMwIiwgCiJFTlNNVVNHMDAwMDAwOTQ2NTIiLCAiRU5TTVVTRzAwMDAwMDk1ODU5IiwgIkVOU01VU0cwMDAwMDAzMTI2NCIsIAoiRU5TTVVTRzAwMDAwMDQyNjcyIiwgIkVOU01VU0cwMDAwMDAzNDQyMiIsICJFTlNNVVNHMDAwMDAwNzY3MDkiLCAKIkVOU01VU0cwMDAwMDA5NjM1NSIsICJFTlNNVVNHMDAwMDAwNzY3MTAiLCAiRU5TTVVTRzAwMDAwMDIwMzk1IiwgCiJFTlNNVVNHMDAwMDAxMDIzNjQiLCAiRU5TTVVTRzAwMDAwMDk0MTk4IiwgIkVOU01VU0cwMDAwMDAyNDQ1NyIsIAoiRU5TTVVTRzAwMDAwMDI1NTEyIiwgIkVOU01VU0cwMDAwMDAzMjMxMiIsICJFTlNNVVNHMDAwMDAwNTg3MTUiLCAKIkVOU01VU0cwMDAwMDA5NTIwNCIsICJFTlNNVVNHMDAwMDAwOTM4OTQiLCAiRU5TTVVTRzAwMDAwMDk0NTA1IiwgCiJFTlNNVVNHMDAwMDAwNzg5NDUiLCAiRU5TTVVTRzAwMDAwMDMyNjkxIiwgIkVOU01VU0cwMDAwMDAxNTA4MyIsIAoiRU5TTVVTRzAwMDAwMDk0Nzg3IiwgIkVOU01VU0cwMDAwMDAxNDU5OSIsICJFTlNNVVNHMDAwMDAwMjEyNzciLCAKIkVOU01VU0cwMDAwMDA5NTU4OSIsICJFTlNNVVNHMDAwMDAwOTQ4NjIiLCAiRU5TTVVTRzAwMDAwMDMxMTAzIiwgCiJFTlNNVVNHMDAwMDAwNDk1MDIiLCAiRU5TTVVTRzAwMDAwMDMxMzkyIiwgIkVOU01VU0cwMDAwMDA3ODk0MiIsIAoiRU5TTVVTRzAwMDAwMDIyOTA2IiwgIkVOU01VU0cwMDAwMDEwNDQ1MiIsICJFTlNNVVNHMDAwMDAwOTU4ODkiLCAKIkVOU01VU0cwMDAwMDAzOTkzNiIsICJFTlNNVVNHMDAwMDAwMDMyODMiLCAiRU5TTVVTRzAwMDAwMDk1MTk3IiwgCiJFTlNNVVNHMDAwMDAwMjE2MjQiLCAiRU5TTVVTRzAwMDAwMDAzMTg0IiwgIkVOU01VU0cwMDAwMDA5NDA4NyIsIAoiRU5TTVVTRzAwMDAwMTAyMzEzIiwgIkVOU01VU0cwMDAwMDA1OTEyOCIsICJFTlNNVVNHMDAwMDAwMDI5ODMiLCAKIkVOU01VU0cwMDAwMDA2MDc0NyIsICJFTlNNVVNHMDAwMDAwMTk4NDMiLCAiRU5TTVVTRzAwMDAwMDk2MDc4IiwgCiJFTlNNVVNHMDAwMDAwOTY3NjciLCAiRU5TTVVTRzAwMDAwMDY2NTUxIiwgIkVOU01VU0cwMDAwMDA2MjU0NSIsIAoiRU5TTVVTRzAwMDAwMDk1MTE3IiwgIkVOU01VU0cwMDAwMDAxNDkzMiIsICJFTlNNVVNHMDAwMDAwOTY2NzIiLCAKIkVOU01VU0cwMDAwMDA5NDA4OCIsICJFTlNNVVNHMDAwMDAwMzg1MTciLCAiRU5TTVVTRzAwMDAwMDMwNDY4IiwgCiJFTlNNVVNHMDAwMDAwOTUxNzAiLCAiRU5TTVVTRzAwMDAwMDk1NTE5IiwgIkVOU01VU0cwMDAwMDAyNjM2NSIsIAoiRU5TTVVTRzAwMDAwMDI5ODI2IiwgIkVOU01VU0cwMDAwMDA5NTg2MyIsICJFTlNNVVNHMDAwMDAwOTQ1MDIiLCAKIkVOU01VU0cwMDAwMDA3NjczMSIsICJFTlNNVVNHMDAwMDAwMjAzOTkiLCAiRU5TTVVTRzAwMDAwMDczNzMwIiwgCiJFTlNNVVNHMDAwMDAwNTE2NzUiLCAiRU5TTVVTRzAwMDAwMDc2NzMzIiwgIkVOU01VU0cwMDAwMDAyNDE2NCIsIAoiRU5TTVVTRzAwMDAwMDk0MTI0IiwgIkVOU01VU0cwMDAwMDA0MTAwMCIsICJFTlNNVVNHMDAwMDAwNDg4NzgiLCAKIkVOU01VU0cwMDAwMDAzNzIzNiIsICJFTlNNVVNHMDAwMDAwOTYwMjAiLCAiRU5TTVVTRzAwMDAwMDE3MDAyIiwgCiJFTlNNVVNHMDAwMDAwNTc5ODIiLCAiRU5TTVVTRzAwMDAwMDc1MzcwIiwgIkVOU01VU0cwMDAwMDAzNzQ0NyIsIAoiRU5TTVVTRzAwMDAwMDI1MTM5IiwgIkVOU01VU0cwMDAwMDAzOTAwNSIsICJFTlNNVVNHMDAwMDAwMjE0NTciLCAKIkVOU01VU0cwMDAwMDA3MzQxOCIsICJFTlNNVVNHMDAwMDAwMDQ3MDkiLCAiRU5TTVVTRzAwMDAwMDAxMzY2IiwgCiJFTlNNVVNHMDAwMDAwMDQ3MDciLCAiRU5TTVVTRzAwMDAwMDQ4ODA2IiwgIkVOU01VU0cwMDAwMDA0OTQxMCIsIAoiRU5TTVVTRzAwMDAwMDk2MDExIiwgIkVOU01VU0cwMDAwMDA5NTI3MCIsICJFTlNNVVNHMDAwMDAwOTU4OTYiLCAKIkVOU01VU0cwMDAwMDA3MzgxMSIsICJFTlNNVVNHMDAwMDAwMDA0MDkiLCAiRU5TTVVTRzAwMDAwMDE3NzA3IiwgCiJFTlNNVVNHMDAwMDAwMzg3NDUiLCAiRU5TTVVTRzAwMDAwMDM4MzU3IiwgIkVOU01VU0cwMDAwMDA2MzM3NiIsIAoiRU5TTVVTRzAwMDAwMDc4MzU1IiwgIkVOU01VU0cwMDAwMDEwMDA3OSIsICJFTlNNVVNHMDAwMDAwNDIyMjgiLCAKIkVOU01VU0cwMDAwMDA5NDYxOCIsICJFTlNNVVNHMDAwMDAxMDA1MDUiLCAiRU5TTVVTRzAwMDAwMDk0MjcxIiwgCiJFTlNNVVNHMDAwMDAwOTY1ODIiLCAiRU5TTVVTRzAwMDAwMDk2NTkxIiwgIkVOU01VU0cwMDAwMDA0NzEzOSIsIAoiRU5TTVVTRzAwMDAwMDM3Mzc5IiwgIkVOU01VU0cwMDAwMDA1MDE5OSIsICJFTlNNVVNHMDAwMDAwOTY4NTQiLCAKIkVOU01VU0cwMDAwMDA5OTU0NSIsICJFTlNNVVNHMDAwMDAxMDAyMzQiLCAiRU5TTVVTRzAwMDAwMTAxMTYzIiwgCiJFTlNNVVNHMDAwMDAwMzE2MzkiLCAiRU5TTVVTRzAwMDAwMDk5NTE4IiwgIkVOU01VU0cwMDAwMDA5OTQyMCIsIAoiRU5TTVVTRzAwMDAwMDk1MTAxIiwgIkVOU01VU0cwMDAwMDA5NDY0OCIsICJFTlNNVVNHMDAwMDAwNzA5MDgiLCAKIkVOU01VU0cwMDAwMDEwMDU0OSIsICJFTlNNVVNHMDAwMDAwNzA5MDQiLCAiRU5TTVVTRzAwMDAwMDMyNjkwIiwgCiJFTlNNVVNHMDAwMDAwMDI2ODgiLCAiRU5TTVVTRzAwMDAwMDMyNjYxIiwgIkVOU01VU0cwMDAwMDAxNTMxNiIsIAoiRU5TTVVTRzAwMDAwMDI2MzkwIiwgIkVOU01VU0cwMDAwMDA0NTM2NCIsICJFTlNNVVNHMDAwMDAwMDkyODEiLCAKIkVOU01VU0cwMDAwMDAzMDE0OCIsICJFTlNNVVNHMDAwMDAwNTE2ODIiLCAiRU5TTVVTRzAwMDAwMDUyNzc2IiwgCiJFTlNNVVNHMDAwMDAwMTUzMTQiLCAiRU5TTVVTRzAwMDAwMDI2OTM4IiwgIkVOU01VU0cwMDAwMDA1MDEzMiIsIAoiRU5TTVVTRzAwMDAwMDM4MTYwIiwgIkVOU01VU0cwMDAwMDAzNDMxNyIsICJFTlNNVVNHMDAwMDAwMjMzNDkiLCAKIkVOU01VU0cwMDAwMDAyOTc5OCIsICJFTlNNVVNHMDAwMDAwNDExMzUiLCAiRU5TTVVTRzAwMDAwMDQ2ODc5IiwgCiJFTlNNVVNHMDAwMDAwMzgxNTEiLCAiRU5TTVVTRzAwMDAwMDI2ODc0IiwgIkVOU01VU0cwMDAwMDAzMDE0NCIsIAoiRU5TTVVTRzAwMDAwMDMwMTQyIiwgIkVOU01VU0cwMDAwMDA1NjEzMCIsICJFTlNNVVNHMDAwMDAwMjM5OTIiLCAKIkVOU01VU0cwMDAwMDA0NDcwMSIsICJFTlNNVVNHMDAwMDAwMTk3NzkiLCAiRU5TTVVTRzAwMDAwMDMzMzA3IiwgCiJFTlNNVVNHMDAwMDAwNTk0NTYiLCAiRU5TTVVTRzAwMDAwMDM4NTI3IiwgIkVOU01VU0cwMDAwMDAyNTQ5OCIsIAoiRU5TTVVTRzAwMDAwMDU1MTcyIiwgIkVOU01VU0cwMDAwMDA5ODQ3MCIsICJFTlNNVVNHMDAwMDAwNzkzNDMiLCAKIkVOU01VU0cwMDAwMDAzODYyOCIsICJFTlNNVVNHMDAwMDAwMjc1MTQiLCAiRU5TTVVTRzAwMDAwMDIyMDQzIiwgCiJFTlNNVVNHMDAwMDAwMjUzODMiLCAiRU5TTVVTRzAwMDAwMDI0MzcxIiwgIkVOU01VU0cwMDAwMDA5MDIzMSIsIAoiRU5TTVVTRzAwMDAwMDI1MzMwIiwgIkVOU01VU0cwMDAwMDAzNDg4OSIsICJFTlNNVVNHMDAwMDAwMjg5NzkiLCAKIkVOU01VU0cwMDAwMDAzMDExNCIsICJFTlNNVVNHMDAwMDAwMjExMjUiLCAiRU5TTVVTRzAwMDAwMDM4NzUxIiwgCiJFTlNNVVNHMDAwMDAwNzkyOTMiLCAiRU5TTVVTRzAwMDAwMDIwNzA3IiwgIkVOU01VU0cwMDAwMDA1NDg5MiIsIAoiRU5TTVVTRzAwMDAwMDMwMTQ5IiwgIkVOU01VU0cwMDAwMDAyMDgyMyIsICJFTlNNVVNHMDAwMDAwMjU1MzIiLCAKIkVOU01VU0cwMDAwMDAzMjg5OSIsICJFTlNNVVNHMDAwMDAwMjQzNDkiLCAiRU5TTVVTRzAwMDAwMDMyOTA1IiwgCiJFTlNNVVNHMDAwMDAwOTA0ODUiLCAiRU5TTVVTRzAwMDAwMDU0MDcyIiwgIkVOU01VU0cwMDAwMDAyMjQ3NiIsIAoiRU5TTVVTRzAwMDAwMDI0NDA0IiwgIkVOU01VU0cwMDAwMDA1MTQzOSIsICJFTlNNVVNHMDAwMDAwOTY2MjEiLCAKIkVOU01VU0cwMDAwMDAyNDg2MyIsICJFTlNNVVNHMDAwMDAwMjQwNDUiLCAiRU5TTVVTRzAwMDAwMDI2MTg3IiwgCiJFTlNNVVNHMDAwMDAwMjUyMjUiLCAiRU5TTVVTRzAwMDAwMDIyODg3IiwgIkVOU01VU0cwMDAwMDAyNTAzNCIsIAoiRU5TTVVTRzAwMDAwMDU2ODUxIiwgIkVOU01VU0cwMDAwMDA1NjYxMiIsICJFTlNNVVNHMDAwMDAwMjI1NzUiLCAKIkVOU01VU0cwMDAwMDAwMDEyNyIsICJFTlNNVVNHMDAwMDAwNDIzNTEiLCAiRU5TTVVTRzAwMDAwMDM5MTkzIiwgCiJFTlNNVVNHMDAwMDAxMDY4NTAiKSksIC5OYW1lcyA9IGMoIm1naV9zeW1ib2wiLCAiZXh0ZXJuYWxfZ2VuZV9uYW1lIiwgCiJlbnNlbWJsX2dlbmVfaWQiKSwgY2xhc3MgPSAiZGF0YS5mcmFtZSIsIHJvdy5uYW1lcyA9IGMoTkEsIC01MjdMCikpCmBgYAoKYGBge3J9CnJlc3VsdHNfaW50ZXJmZXJvbl9yZXNwb25zZV9pbW11bmUKYGBgCgojIyBSdW4gUENBIGFuZCB0LVNORSBmb3IgdGhlIHlvdW5nIHZzIG9sZCBTbWFydFNlcTIgZGF0YQoKYGBge3J9CnNldXJhdF9zbXMyIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IHNldXJhdF9zbXMyLCBtZWFuLmZ1bmN0aW9uID0gRXhwTWVhbiwgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwgCiAgICB5LmN1dG9mZiA9IDAuNzUpCmBgYAoKYGBge3J9CmdlbmVzLnZhciA8LSBhcHBseShYID0gc2V1cmF0X3NtczJAcmF3LmRhdGEgLCBNQVJHSU4gPSAxICwgRlVOID0gdmFyKQpnZW5lcy52YXIudG9wIDwtIG5hbWVzKCBzb3J0KGdlbmVzLnZhciAsIGRlY3JlYXNpbmcgPSBUUlVFKVsxOjIwMDBdICkKCnNldXJhdF9zbXMyQHZhci5nZW5lcyA8LSBnZW5lcy52YXIudG9wCmBgYAoKYGBge3J9CnNldXJhdF9zbXMyQGltcHV0ZWQgPC0gYXMuZGF0YS5mcmFtZS5tYXRyaXgoc2V1cmF0X3NtczJAZGF0YSkKYGBgCgoKYGBge3J9CnNldXJhdF9zbXMyIDwtIFJ1blBDQShvYmplY3QgPSBzZXVyYXRfc21zMiwgcGMuZ2VuZXMgPSBzZXVyYXRfc21zMkB2YXIuZ2VuZXMsIGRvLnByaW50ID0gVFJVRSwgcGNzLnByaW50ID0gMTo1LCBnZW5lcy5wcmludCA9IDUgLCB1c2UuaW1wdXRlZCA9IFRSVUUgKQpzZXVyYXRfc21zMiA8LSBQcm9qZWN0UENBKG9iamVjdCA9IHNldXJhdF9zbXMyICkKc2V1cmF0X3NtczIgPC0gSmFja1N0cmF3KG9iamVjdCA9IHNldXJhdF9zbXMyICApCmBgYAoKYGBge3J9ClBDRWxib3dQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyKQpgYGAKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBTZXRBbGxJZGVudChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGlkID0gInR5cGUiKQpgYGAKCgpgYGB7cn0KUENBUGxvdChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGRpbS4xID0gMSwgZGltLjIgPSAyKQpgYGAKCmBgYHtyfQpQQ0FQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyICwgZGltLjEgPSAxLCBkaW0uMiA9IDMpCmBgYAoKYGBge3J9ClBDQVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBkaW0uMSA9IDIsIGRpbS4yID0gMykKYGBgCgoKYGBge3J9CnNldXJhdF9zbXMyIDwtIFJ1blRTTkUoc2V1cmF0X3NtczIsIGRpbXMudXNlID0gYygxLDIsMykgLCBkby5mYXN0ID0gVCAsIHNlZWQudXNlID0gMSkKYGBgCgoKYGBge3J9CnNldXJhdF9zbXMyIDwtIFNldEFsbElkZW50KG9iamVjdCA9IHNldXJhdF9zbXMyICwgaWQgPSAidHlwZSIpCmBgYAoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyKQpgYGAKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBTZXRBbGxJZGVudChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGlkID0gImFnZSIpCmBgYAoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyKQpgYGAKCgojIFBDQSBwbG90IFBDMSB2cyBQQzIgd2l0aCBjb2xvcgoKYGBge3J9CnNldXJhdF9zbXMyQG1ldGEuZGF0YSR0eXBlX2xvbmcgPC0gc2V1cmF0X3NtczJAbWV0YS5kYXRhJHR5cGUKCnNldXJhdF9zbXMyQG1ldGEuZGF0YSR0eXBlX2xvbmcgPC0gcmVjb2RlX2ZhY3Rvciggc2V1cmF0X3NtczJAbWV0YS5kYXRhJHR5cGVfbG9uZyAsIHExID0gInFOU0MxIiwgcTIgPSAicU5TQzIiLCBhMSA9ICJhTlNDMSIgLCBhMiA9ICJhTlNDMiIgKQpgYGAKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBTZXRBbGxJZGVudChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGlkID0gInR5cGVfbG9uZyIpCmBgYAoKYGBge3J9ClBDQVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBkaW0uMSA9IDEsIGRpbS4yID0gMiAsIGNvbHMudXNlID0gYyhxTlNDMSA9ICJzdGVlbGJsdWUiICwgcU5TQzIgPSAic3RlZWxibHVlMSIgLCBhTlNDMSA9ICJ0b21hdG8iICwgYU5TQzIgPSAic2llbm5hMSIpICwgcHQuc2hhcGUgPSAiYWdlIikKYGBgCgpgYGB7cn0KZ2dfcGNhIDwtIFBDQVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBkaW0uMSA9IDEsIGRpbS4yID0gMiAsIGNvbHMudXNlID0gYyhxTlNDMSA9ICJzdGVlbGJsdWUiICwgcU5TQzIgPSAic3RlZWxibHVlMSIgLCBhTlNDMSA9ICJ0b21hdG8iICwgYU5TQzIgPSAic2llbm5hMSIpICwgcHQuc2hhcGUgPSAiYWdlIiwgZG8ucmV0dXJuID0gVFJVRSkKYGBgCgoKYGBge3J9CmdnX3BjYV8yIDwtIGdncGxvdChkYXRhID0gZ2dfcGNhJGRhdGEgLCBhZXMoeCA9IHggLCB5ID0geSAsIGNvbG9yID0gaWRlbnQgLCBzaGFwZSA9IHB0LnNoYXBlKSkgKyBnZW9tX3BvaW50KCkgKyB0aGVtZV9idygpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSApICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMocU5TQzEgPSAic3RlZWxibHVlIiAsIHFOU0MyID0gInN0ZWVsYmx1ZTEiICwgYU5TQzEgPSAidG9tYXRvIiAsIGFOU0MyID0gInNpZW5uYTEiKSAsIGxpbWl0cyA9IGMoInFOU0MxIiwicU5TQzIiLCJhTlNDMSIsImFOU0MyIikgLCAiQWN0aXZhdGlvbiBzdGF0ZSIpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMob2xkID0gMTcgLCB5b3VuZyA9IDE2KSAsICJBZ2UiKSArIGNvb3JkX2VxdWFsKCkgKyB4bGFiKCJQQzEiKSArIHlsYWIoIlBDMiIpCgpwcmludChnZ19wY2FfMikKYGBgCmBgYHtyfQpzZCA8LSAgR2V0RGltUmVkdWN0aW9uKG9iamVjdCA9IHNldXJhdF9zbXMyICwgcmVkdWN0aW9uLnR5cGUgPSAicGNhIiAsIHNsb3QgPSAic2RldiIpIApwY19wZXJjZW50YWdlX29mX3ZhcmlhbmNlIDwtIHJvdW5kKCAoc2ReMi9zdW0oc2ReMikpKjEwMCAsIGRpZ2l0cyA9IDEgKQoKZ2dfcGNhX2hvbGxvd2NpcmNsZSA8LSBnZ3Bsb3QoZGF0YSA9IGdnX3BjYSRkYXRhICwgYWVzKHggPSB4ICwgeSA9IHkgLCBjb2xvciA9IGlkZW50ICwgc2hhcGUgPSBwdC5zaGFwZSkpICsgZ2VvbV9wb2ludCgpICsgdGhlbWVfYncoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkgKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKHFOU0MxID0gInN0ZWVsYmx1ZSIgLCBxTlNDMiA9ICJzdGVlbGJsdWUxIiAsIGFOU0MxID0gInRvbWF0byIgLCBhTlNDMiA9ICJzaWVubmExIikgLCBsaW1pdHMgPSBjKCJxTlNDMSIsInFOU0MyIiwiYU5TQzEiLCJhTlNDMiIpICwgIkFjdGl2YXRpb24gc3RhdGUiKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKG9sZCA9IDE3ICwgeW91bmcgPSAxKSAsICJBZ2UiKSArIGNvb3JkX2VxdWFsKCkgKyB4bGFiKCBwYXN0ZSgiUEMxICgiLHBjX3BlcmNlbnRhZ2Vfb2ZfdmFyaWFuY2VbMV0sIiUpIikgKSArIHlsYWIoIHBhc3RlKCJQQzIgKCIscGNfcGVyY2VudGFnZV9vZl92YXJpYW5jZVsyXSwiJSkiICkpICsgY29vcmRfZXF1YWwoKQoKcHJpbnQoZ2dfcGNhX2hvbGxvd2NpcmNsZSkKYGBgCgoKCmBgYHtyIGZpZy53aWR0aD02fQoKZ2dfcGNhXzMgPC0gZ2dwbG90KGRhdGEgPSBnZ19wY2EkZGF0YSAsIGFlcyh4ID0geCAsIHkgPSB5ICwgZmlsbCA9IGZhY3RvcihpZGVudCwgbGV2ZWxzID0gYygicU5TQzEiLCJxTlNDMiIsImFOU0MxIiwiYU5TQzIiKSkgLCBzaGFwZSA9IHB0LnNoYXBlKSApICsgZ2VvbV9wb2ludChzaXplID0gMiwgY29sb3IgPSAiYmxhY2siICkgICsgdGhlbWVfYncoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkgKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMocU5TQzEgPSAic3RlZWxibHVlIiAsIHFOU0MyID0gInN0ZWVsYmx1ZTEiICwgYU5TQzEgPSAidG9tYXRvIiAsIGFOU0MyID0gInNpZW5uYTEiKSAsIGxpbWl0cyA9IGMoInFOU0MxIiwicU5TQzIiLCJhTlNDMSIsImFOU0MyIikgLCAiQWN0aXZhdGlvbiBzdGF0ZSIpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMob2xkID0gMjQgLCB5b3VuZyA9IDIxKSAsICJBZ2UiKSArIGNvb3JkX2VxdWFsKCkgICsgeGxhYiggcGFzdGUoIlBDMSAoIixwY19wZXJjZW50YWdlX29mX3ZhcmlhbmNlWzFdLCIlKSIpICkgKyB5bGFiKCBwYXN0ZSgiUEMyICgiLHBjX3BlcmNlbnRhZ2Vfb2ZfdmFyaWFuY2VbMl0sIiUpIiApKSArIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcz1saXN0KHNoYXBlPTIxKSkpCgpwcmludChnZ19wY2FfMykKYGBgCgpgYGB7ciBmaWcud2lkdGg9Nn0KZ2dfcGNhX2FnZSA8LSBnZ3Bsb3QoZGF0YSA9IGdnX3BjYSRkYXRhICwgYWVzKHggPSB4ICwgeSA9IHkgLCBmaWxsID0gcHQuc2hhcGUgLCBzaGFwZSA9IHB0LnNoYXBlKSApICsgZ2VvbV9wb2ludChzaXplID0gMiwgY29sb3IgPSAiYmxhY2siICkgICsgdGhlbWVfYncoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkgKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoICJvbGQiID0gICJzbGF0ZWJsdWUiLCAieW91bmciID0gInllbGxvd2dyZWVuIikgLCBsYWJlbHMgPSBjKCAib2xkIiAsICJ5b3VuZyIgKSAsIG5hbWUgPSAiQWdlIiApICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMob2xkID0gMjQgLCB5b3VuZyA9IDIxKSAsICJBZ2UiKSArIGNvb3JkX2VxdWFsKCkgICsgeGxhYiggcGFzdGUoIlBDMSAoIixwY19wZXJjZW50YWdlX29mX3ZhcmlhbmNlWzFdLCIlKSIpICkgKyB5bGFiKCBwYXN0ZSgiUEMyICgiLHBjX3BlcmNlbnRhZ2Vfb2ZfdmFyaWFuY2VbMl0sIiUpIiApKSArIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcz1saXN0KHNoYXBlPTIxKSkpCgpwcmludChnZ19wY2FfYWdlKQpgYGAKCiMgTWFrZSBQQ0EgcGxvdHMgZm9yIGVhY2ggc3VicG9wdWxhdGlvbgoKYGBge3J9CmFnZV9jb2xvcnMgPC0gYyh5b3VuZyA9ICJ5ZWxsb3dncmVlbiIgLCBvbGQgPSAic2xhdGVibHVlIikKYGBgCgoKYGBge3J9ClBDQVBsb3Rfc2V1cmF0IDwtIGZ1bmN0aW9uKG9iamVjdCAsIGRpbTEgPSAxLCBkaW0yID0gMiAsIHNjYWxlX3Bjc19ieV9zZCA9IFRSVUUgLCBwdC5zaXplID0gMil7CgogIGdnX3BjYSA8LSBQQ0FQbG90KG9iamVjdCA9IG9iamVjdCAsIGRpbS4xID0gZGltMSwgZGltLjIgPSBkaW0yICwgY29scy51c2UgPSBjKHFOU0MxID0gInN0ZWVsYmx1ZSIgLCBxTlNDMiA9ICJzdGVlbGJsdWUxIiAsIGFOU0MxID0gInRvbWF0byIgLCBhTlNDMiA9ICJzaWVubmExIikgLCBwdC5zaGFwZSA9ICJhZ2UiLCBkby5yZXR1cm4gPSBUUlVFICkKICAKICBzZCA8LSBHZXREaW1SZWR1Y3Rpb24ob2JqZWN0ID0gb2JqZWN0ICwgcmVkdWN0aW9uLnR5cGUgPSAicGNhIiAsIHNsb3QgPSAic2RldiIpCiAgcG92IDwtIHJvdW5kKCAoc2ReMi9zdW0oc2ReMikpKjEwMCAsIGRpZ2l0cyA9IDEgKQogICAgCiAgaWYoc2NhbGVfcGNzX2J5X3NkKXsKICAgIGdnX3BjYSRkYXRhJHggPC0gZ2dfcGNhJGRhdGEkeCAqIHNkW1tkaW0xXV0KICAgIGdnX3BjYSRkYXRhJHkgPC0gZ2dfcGNhJGRhdGEkeSAqIHNkW1tkaW0yXV0KICB9CiAgCiAgeGxpbWl0cyA8LSBOVUxMCiAgeWxpbWl0cyA8LSBOVUxMCiAgICAKICB4X3JhbmdlIDwtIHJhbmdlKGdnX3BjYSRkYXRhJHgpCiAgeF9kaWZmIDwtIHhfcmFuZ2VbMl0teF9yYW5nZVsxXSAKICAKICB5X3JhbmdlICA8LSByYW5nZShnZ19wY2EkZGF0YSR5KQogIHlfZGlmZiA8LSB5X3JhbmdlWzJdLXlfcmFuZ2VbMV0gCgogIGlmKHhfZGlmZiA+IHlfZGlmZil7CiAgICAKICAgIG9mZnNldCA8LSAoKCB4X2RpZmYgLSB5X2RpZmYgKSAvIDIgKQogICAgCiAgICB5X3JhbmdlWzFdIDwtIHlfcmFuZ2VbMV0gLSBvZmZzZXQKICAgIHlfcmFuZ2VbMl0gPC0geV9yYW5nZVsyXSArIG9mZnNldAoKICAgIHlsaW1pdHMgPC0geV9yYW5nZQogICAgICAgIAogIH1lbHNlIGlmKCB5X2RpZmYgPiB4X2RpZmYgKXsKICAgIAogICAgb2Zmc2V0IDwtICgoIHlfZGlmZiAtIHhfZGlmZiApIC8gMiApCiAgICAKICAgIHhfcmFuZ2VbMV0gPC0geF9yYW5nZVsxXSAtIG9mZnNldAogICAgeF9yYW5nZVsyXSA8LSB4X3JhbmdlWzJdICsgb2Zmc2V0CiAgCiAgICB4bGltaXRzIDwtIHhfcmFuZ2UKICAgIAogIH0KICAKICBnZyA8LSBnZ3Bsb3QoZGF0YSA9IGdnX3BjYSRkYXRhICwgYWVzKHggPSB4ICwgeSA9IHkgLCBmaWxsID0gcHQuc2hhcGUgLCBzaGFwZSA9IHB0LnNoYXBlKSApICsgZ2VvbV9wb2ludChzaXplID0gcHQuc2l6ZSwgY29sb3VyID0gImJsYWNrIikgKyB0aGVtZV9idygpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSApICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYWdlX2NvbG9ycyAsIGxpbWl0cyA9IG5hbWVzKGFnZV9jb2xvcnMpICwgbmFtZSA9ICJBZ2UiKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKG9sZCA9IDI0ICwgeW91bmcgPSAyMSkgLCBsaW1pdHMgPSBuYW1lcyhhZ2VfY29sb3JzKSAsIG5hbWUgPSAiQWdlIikgKyBjb29yZF9lcXVhbCgpICArIHhsYWIocGFzdGUoIlBDIixkaW0xLCIgKCIscG92W2RpbTFdLCIlKSIpKSArIHlsYWIocGFzdGUoIlBDIixkaW0yLCIgKCIscG92W2RpbTJdLCAiJSkiKSkgKyBnZ3RpdGxlKHBhc3RlMCh1bmlxdWUoZ2dfcGNhJGRhdGEkaWRlbnQpKSApICsgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKQogIAogIGlmKCFpcy5udWxsKHhsaW1pdHMpKXtnZyA8LSBnZyArIHhsaW0oIHhsaW1pdHMgKX0KICBpZighaXMubnVsbCh5bGltaXRzKSl7Z2cgPC0gZ2cgKyB5bGltKCB5bGltaXRzICl9CiAgCiAgZ2cKfQpgYGAKCgpgYGB7cn0KVFNORVBsb3RfU2V1cmF0IDwtIGZ1bmN0aW9uKHggLCB0aXRsZSA9ICIiKXsKCiAgeGxpbWl0cyA8LSBOVUxMCiAgeWxpbWl0cyA8LSBOVUxMCiAgICAKICB4X3JhbmdlIDwtIHJhbmdlKHgkdFNORV8xKQogIHhfZGlmZiA8LSB4X3JhbmdlWzJdLXhfcmFuZ2VbMV0gCiAgCiAgeV9yYW5nZSAgPC0gcmFuZ2UoeCR0U05FXzIpCiAgeV9kaWZmIDwtIHlfcmFuZ2VbMl0teV9yYW5nZVsxXSAKCiAgaWYoeF9kaWZmID4geV9kaWZmKXsKICAgIAogICAgb2Zmc2V0IDwtICgoIHhfZGlmZiAtIHlfZGlmZiApIC8gMiApCiAgICAKICAgIHlfcmFuZ2VbMV0gPC0geV9yYW5nZVsxXSAtIG9mZnNldAogICAgeV9yYW5nZVsyXSA8LSB5X3JhbmdlWzJdICsgb2Zmc2V0CgogICAgeWxpbWl0cyA8LSB5X3JhbmdlCiAgICAgICAgCiAgfWVsc2UgaWYoIHlfZGlmZiA+IHhfZGlmZiApewogICAgCiAgICBvZmZzZXQgPC0gKCggeV9kaWZmIC0geF9kaWZmICkgLyAyICkKICAgIAogICAgeF9yYW5nZVsxXSA8LSB4X3JhbmdlWzFdIC0gb2Zmc2V0CiAgICB4X3JhbmdlWzJdIDwtIHhfcmFuZ2VbMl0gKyBvZmZzZXQKICAKICAgIHhsaW1pdHMgPC0geF9yYW5nZQogIH0KICAgIAogIGdnIDwtIGdncGxvdChkYXRhID0geCAsIG1hcHBpbmcgPSBhZXMoeCA9IHRTTkVfMSAsIHkgPSB0U05FXzIgLCBmaWxsID0gYWdlICAsIHNoYXBlID0gYWdlKSkgKyBnZW9tX3BvaW50KHNpemUgPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoICJvbGQiID0gICJzbGF0ZWJsdWUiLCAieW91bmciID0gInllbGxvd2dyZWVuIikgLCBsYWJlbHMgPSBjKCAib2xkIiAsICJ5b3VuZyIgKSAsIG5hbWUgPSAiQWdlIiApICsgbGFicyggeCA9ICJ0U05FIDEiICwgeSA9ICJ0U05FIDIiICkgKyBjb29yZF9lcXVhbCgpICsgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCAib2xkIiA9IDI0ICwgInlvdW5nIiA9IDIxKSAsIGxhYmVscyA9IGMoICJvbGQiICwgInlvdW5nIiApICwgbmFtZSA9ICJBZ2UiKSArIGdndGl0bGUoIHRpdGxlICkKICAKICBpZighaXMubnVsbCh4bGltaXRzKSl7Z2cgPC0gZ2cgKyB4bGltKCB4bGltaXRzICl9CiAgaWYoIWlzLm51bGwoeWxpbWl0cykpe2dnIDwtIGdnICsgeWxpbSggeWxpbWl0cyApfQogIAogIGdnCn0KYGBgCgojIyBxTlNDMQoKYGBge3J9CnNldXJhdF9zbXMyX3FOU0MxIDwtIFN1YnNldERhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBpZGVudC51c2UgPSAicU5TQzEiKQpzZXVyYXRfc21zMl9xTlNDMSA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMSAsIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLCBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SKQpzZXVyYXRfc21zMl9xTlNDMSA8LSBSdW5QQ0Eob2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzEgLCBkby5wcmludCA9IEZBTFNFICkKCnBjYV9xMSA8LSBQQ0FQbG90X3NldXJhdCggb2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzEgLCBkaW0xID0gMSwgZGltMiA9IDIgKQoKcGNhX3ExCgpQQ0FQbG90X3NldXJhdCggb2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzEgLCBkaW0xID0gMiwgZGltMiA9IDMgKQoKUENfdG9wNTBnZW5lc19xTlNDMTwtIGJpbmRfY29scyggbGFwcGx5KCBsaXN0KFBDMSA9IDEsIFBDMiA9IDIgLCBQQzMgPSAzKSAsICBGVU49ZnVuY3Rpb24oeCl7UENUb3BHZW5lcyhvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMSAsIHBjLnVzZSA9IHggLCBudW0uZ2VuZXMgPSA1MCApfSApICkKCgpQQ0VsYm93UGxvdChvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMSkKCnNldXJhdF9zbXMyX3FOU0MxIDwtIFJ1blRTTkUob2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzEgLCBkaW1zLnVzZSA9IDE6NCAsIHNlZWQudXNlID0gMSApCgpUU05FUGxvdChvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMSApIAoKCnggPC0gRmV0Y2hEYXRhKCBvYmplY3QgPSAgc2V1cmF0X3NtczJfcU5TQzEgLCB2YXJzLmFsbCA9IGMoInRTTkVfMSIsInRTTkVfMiIsImFnZSIpICkKCmdnX3RzbmVfcU5TQzEgPC0gVFNORVBsb3RfU2V1cmF0KHggPSB4ICwgdGl0bGUgPSAicU5TQzEiKSAKCmdnX3RzbmVfcU5TQzEKYGBgCgojIyBxTlNDMgoKYGBge3J9CnNldXJhdF9zbXMyX3FOU0MyIDwtIFN1YnNldERhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBpZGVudC51c2UgPSAicU5TQzIiKQpzZXVyYXRfc21zMl9xTlNDMiA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMiAsIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLCBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SKQpzZXVyYXRfc21zMl9xTlNDMiA8LSBSdW5QQ0Eob2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzIgLCBkby5wcmludCA9IEZBTFNFKQoKcGNhX3EyIDwtIFBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMiAsIGRpbTEgPSAxLCBkaW0yID0gMiApCgpwY2FfcTIKClBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMiAsIGRpbTEgPSAyLCBkaW0yID0gMyApCgpQQ190b3A1MGdlbmVzX3FOU0MyPC0gYmluZF9jb2xzKCBsYXBwbHkoIGxpc3QoUEMxID0gMSwgUEMyID0gMiAsIFBDMyA9IDMpICwgIEZVTj1mdW5jdGlvbih4KXtQQ1RvcEdlbmVzKG9iamVjdCA9IHNldXJhdF9zbXMyX3FOU0MyICwgcGMudXNlID0geCAsIG51bS5nZW5lcyA9IDUwICl9ICkgKQoKCgpQQ0VsYm93UGxvdChvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMikKCnNldXJhdF9zbXMyX3FOU0MyIDwtIFJ1blRTTkUob2JqZWN0ID0gc2V1cmF0X3NtczJfcU5TQzIgLCBkaW1zLnVzZSA9IDE6NSAsIHNlZWQudXNlID0gMSAsIHBlcnBsZXhpdHkgPSAxMyApCgpUU05FUGxvdChvYmplY3QgPSBzZXVyYXRfc21zMl9xTlNDMiApIAoKCnggPC0gRmV0Y2hEYXRhKCBvYmplY3QgPSAgc2V1cmF0X3NtczJfcU5TQzIgLCB2YXJzLmFsbCA9IGMoInRTTkVfMSIsInRTTkVfMiIsImFnZSIpICkKCmdnX3RzbmVfcU5TQzIgPC0gVFNORVBsb3RfU2V1cmF0KHggPSB4ICwgdGl0bGUgPSAicU5TQzIgKHBlcnBsZXhpdHkgPSAxMykiKSAKCmdnX3RzbmVfcU5TQzIKYGBgCgojIyBhTlNDMQoKYGBge3J9CnNldXJhdF9zbXMyX2FOU0MxIDwtIFN1YnNldERhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBpZGVudC51c2UgPSAiYU5TQzEiKQpzZXVyYXRfc21zMl9hTlNDMSA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMSAsIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLCBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SKQpzZXVyYXRfc21zMl9hTlNDMSA8LSBSdW5QQ0Eob2JqZWN0ID0gc2V1cmF0X3NtczJfYU5TQzEgLCBkby5wcmludCA9IEZBTFNFKQoKcGNhX2ExIDwtIFBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMSAsIGRpbTEgPSAxLCBkaW0yID0gMiApCgpwY2FfYTEKClBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMSAsIGRpbTEgPSAyLCBkaW0yID0gMyApCgpQQ190b3A1MGdlbmVzX2FOU0MxPC0gYmluZF9jb2xzKCBsYXBwbHkoIGxpc3QoUEMxID0gMSwgUEMyID0gMiAsIFBDMyA9IDMpICwgIEZVTj1mdW5jdGlvbih4KXtQQ1RvcEdlbmVzKG9iamVjdCA9IHNldXJhdF9zbXMyX2FOU0MxICwgcGMudXNlID0geCAsIG51bS5nZW5lcyA9IDUwICl9ICkgKQoKClBDRWxib3dQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyX2FOU0MxKQoKc2V1cmF0X3NtczJfYU5TQzEgPC0gUnVuVFNORShvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMSAsIGRpbXMudXNlID0gMTo1ICwgc2VlZC51c2UgPSAxICwgcGVycGxleGl0eSA9IDcgKQoKVFNORVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczJfYU5TQzEgKSAKCgp4IDwtIEZldGNoRGF0YSggb2JqZWN0ID0gIHNldXJhdF9zbXMyX2FOU0MxICwgdmFycy5hbGwgPSBjKCJ0U05FXzEiLCJ0U05FXzIiLCJhZ2UiKSApCgpnZ190c25lX2FOU0MxIDwtIFRTTkVQbG90X1NldXJhdCh4ID0geCAsIHRpdGxlID0gImFOU0MxIChwZXJwbGV4aXR5ID0gNykiKSAKCmdnX3RzbmVfYU5TQzEKYGBgCgojIyBhTlNDMgoKYGBge3J9CnNldXJhdF9zbXMyX2FOU0MyIDwtIFN1YnNldERhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBpZGVudC51c2UgPSAiYU5TQzIiKQpzZXVyYXRfc21zMl9hTlNDMiA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMiAsIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLCBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SKQpzZXVyYXRfc21zMl9hTlNDMiA8LSBSdW5QQ0Eob2JqZWN0ID0gc2V1cmF0X3NtczJfYU5TQzIgLCBkby5wcmludCA9IEZBTFNFKQoKcGNhX2EyIDwtIFBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMiAsIGRpbTEgPSAxLCBkaW0yID0gMiApCgpwY2FfYTIKClBDQVBsb3Rfc2V1cmF0KCBvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMiAsIGRpbTEgPSAyLCBkaW0yID0gMyApCgpQQ190b3A1MGdlbmVzX2FOU0MyPC0gYmluZF9jb2xzKCBsYXBwbHkoIGxpc3QoUEMxID0gMSwgUEMyID0gMiAsIFBDMyA9IDMpICwgIEZVTj1mdW5jdGlvbih4KXtQQ1RvcEdlbmVzKG9iamVjdCA9IHNldXJhdF9zbXMyX2FOU0MyICwgcGMudXNlID0geCAsIG51bS5nZW5lcyA9IDUwICl9ICkgKQoKClBDRWxib3dQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyX2FOU0MyKQoKc2V1cmF0X3NtczJfYU5TQzIgPC0gUnVuVFNORShvYmplY3QgPSBzZXVyYXRfc21zMl9hTlNDMiAsIGRpbXMudXNlID0gMTo1ICwgc2VlZC51c2UgPSAxICwgcGVycGxleGl0eSA9IDcgKQoKVFNORVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczJfYU5TQzIgKSAKCgp4IDwtIEZldGNoRGF0YSggb2JqZWN0ID0gIHNldXJhdF9zbXMyX2FOU0MyICwgdmFycy5hbGwgPSBjKCJ0U05FXzEiLCJ0U05FXzIiLCJhZ2UiKSApCgpnZ190c25lX2FOU0MyIDwtIFRTTkVQbG90X1NldXJhdCh4ID0geCAsIHRpdGxlID0gImFOU0MyIChwZXJwbGV4aXR5ID0gNykiKSAKCmdnX3RzbmVfYU5TQzIKYGBgCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CmdyaWQuYXJyYW5nZShwY2FfcTEscGNhX3EyLHBjYV9hMSxwY2FfYTIpCmBgYAoKCgoKIyB0LVNORSBwbG90cyBvZiBzdWJwb3B1bGF0aW9ucwoKR2F0aGVyIGFsbCB0LVNORSBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCAsIGZpZy53aWR0aD0xMH0KZ3JpZC5hcnJhbmdlKCBnZ190c25lX3FOU0MxICwgZ2dfdHNuZV9xTlNDMiAsIGdnX3RzbmVfYU5TQzEgLCBnZ190c25lX2FOU0MyICkKYGBgCgpgYGB7cn0Kc2F2ZVJEUyhvYmplY3QgPSBzZXVyYXRfc21zMiAsIGZpbGUgPSAic2V1cmF0X3NtczIuUkRTIiApCmBgYAoKIyBGaW5kIGNlbGx0eXBlIG1hcmtlcnMKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBTZXRBbGxJZGVudChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGlkID0gInR5cGVfbG9uZyIpCgpjZWxsdHlwZV9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IHNldXJhdF9zbXMyICx0ZXN0LnVzZSA9ICJ0IiAsIHJhbmRvbS5zZWVkID0gMTIzICkKYGBgCgpgYGB7cn0KY2VsbHR5cGVfbWFya2VycwpgYGAKCiMgU2F2ZSBtYXJrZXJzIG9mIGluZGl2aWR1YWwgY2VsbHR5cGVzCgpgYGB7cn0KY2VsbHR5cGVzIDwtIGMoInFOU0MxIiwicU5TQzIiLCJhTlNDMSIsImFOU0MyIikKCmZvcihpIGluIGNlbGx0eXBlcyl7CiAgd3JpdGUuY3N2KHggPSBjZWxsdHlwZV9tYXJrZXJzICU+JSBmaWx0ZXIoY2x1c3RlciA9PSBpKSAsIGZpbGUgPSBmaWxlLnBhdGgoImNlbGx0eXBlX21hcmtlcnMvIixwYXN0ZTAoImNlbGx0eXBlX21hcmtlcnNfIixpLCJfU21hcnRTZXEyLmNzdiIpKSApCn0KYGBgCgojIEdPIGFuYWx5c2lzIGNsdXN0ZXJDb21wYXJlIGNlbGx0eXBlcwoKYGBge3J9CkRFX3Jlc3VsdHNfbGlzdCA8LSBsaXN0KCkKCmZvcihpIGluIGNlbGx0eXBlcyl7CiAgREVfcmVzdWx0c19saXN0W1tpXV0gPC0gY2VsbHR5cGVfbWFya2VycyAlPiUgZmlsdGVyKGNsdXN0ZXIgPT0gaSkgCn0KYGBgCgojIyBHTyB0ZXJtIGFuYWx5c2lzIGZ1bmN0aW9uCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MjB9CkdPX2FuYWx5c2lzIDwtIGZ1bmN0aW9uKERFX3Jlc3VsdHNfbGlzdCAsIHBfYWRqX2N1dG9mZiA9IDAuMDUgICl7CiAgcmVxdWlyZSgiY2x1c3RlclByb2ZpbGVyIikKICAKICBpZiggbGVuZ3RoKERFX3Jlc3VsdHNfbGlzdCkgPCAxKXsKICAgIHdhcm5pbmcoIk5vIGVudHJpZXMgaW4gREVfcmVzdWx0c19saXN0IikKICAgIGludmlzaWJsZShERV9yZXN1bHRzX2xpc3QpCiAgfQogIAogIGRlX2dlbmVzX2xpc3QgPC1saXN0KE5VTEwpCiAgZm9yKGkgaW4gc2VxX2xlbihsZW5ndGgoREVfcmVzdWx0c19saXN0KSkgKXsKICAgIGRlX2dlbmVzIDwtIERFX3Jlc3VsdHNfbGlzdFtbaV1dICU+JSBmaWx0ZXIoIGF2Z19sb2dGQyA+IDAgKSAlPiUgZHBseXI6OmZpbHRlciggcF92YWxfYWRqIDwgcF9hZGpfY3V0b2ZmICkgJT4lIGRwbHlyOjpwdWxsKGdlbmUpCiAgICAKICAgIGRlX2dlbmVzX2xpc3RbWyBuYW1lcyhERV9yZXN1bHRzX2xpc3RbaV0pIF1dIDwtIGJpdHIoZ2VuZUlEID0gZGVfZ2VuZXMgLCBmcm9tVHlwZSA9ICJFTlNFTUJMIiAsIHRvVHlwZSA9ICJFTlRSRVpJRCIgLCBPcmdEYiA9ICJvcmcuTW0uZWcuZGIiIClbLCJFTlRSRVpJRCJdCiAgfQoKICAgICMgYXZhaWxhYmxlIG9udG9sb2dpZXMgYXJlOgogICAgIyBCUCAtIGJpb2xvZ2ljYWxfcHJvY2VzcwogICAgIyBDQyAtIGNlbGx1bGFyX2NvbXBvbmVudAogICAgIyBNRiAtIG1vbGVjdWxhcl9mdW5jdGlvbgogICAgZ29fcmVzdWx0cyA8LSBjb21wYXJlQ2x1c3RlcihnZW5lQ2x1c3RlcnMgPSBkZV9nZW5lc19saXN0ICwgZnVuID0gImVucmljaEdPIiAsIE9yZ0RiID0gIm9yZy5NbS5lZy5kYiIgLCBvbnQgPSAiQlAiLCBwdmFsdWVDdXRvZmYgPSAwLjA1ICkKICAgICAgCiAgcmV0dXJuKGdvX3Jlc3VsdHMpCn0KYGBgCgpgYGB7cn0Kc21hcnRzZXEyX2NvbXBhcmVfR09fcmVzdWx0cyA8LSBHT19hbmFseXNpcyhERV9yZXN1bHRzX2xpc3QgPSBERV9yZXN1bHRzX2xpc3QgLCBwX2Fkal9jdXRvZmYgPSAwLjAxKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xNSAsIGZpZy5hc3A9MX0KZG90cGxvdCggc21hcnRzZXEyX2NvbXBhcmVfR09fcmVzdWx0cyAsIHNob3dDYXRlZ29yeSA9IDEwKQpgYGAKCgpgYGB7cn0Kc21hcnRzZXEyX2NvbXBhcmVfR09fcmVzdWx0cy5zaW0gPC0gY2x1c3RlclByb2ZpbGVyOjpzaW1wbGlmeShzbWFydHNlcTJfY29tcGFyZV9HT19yZXN1bHRzKSAKYGBgCgoKYGBge3IgZmlnLndpZHRoPTE1ICwgZmlnLmFzcD0xLjV9CmdnMiA8LSBjbHVzdGVyUHJvZmlsZXI6OmRvdHBsb3Qoc21hcnRzZXEyX2NvbXBhcmVfR09fcmVzdWx0cyAsIHNob3dDYXRlZ29yeSA9IDE1KQoKZ2cyJGRhdGEkRGVzY3JpcHRpb24gPC0gZmN0X3JlbGFiZWwoIC5mID0gZ2cyJGRhdGEkRGVzY3JpcHRpb24gLCAuZnVuID0gZnVuY3Rpb24oeCl7c3RyX3dyYXAoc3RyaW5nID0geCAsIHdpZHRoID0gNDApfSApCgpwbG90ZGF0YSA8LSBnZzIkZGF0YSAlPiUgZmlsdGVyKCBwLmFkanVzdCA8IDAuMDUpCgpsZXZlbHMocGxvdGRhdGEkQ2x1c3RlcikgPC0gc3ViKCB4ID0gbGV2ZWxzKHBsb3RkYXRhJENsdXN0ZXIpICwgcGF0dGVybiA9ICJERV9jZWxsdHlwZV9nZW5lc18iLCByZXBsYWNlbWVudCA9ICIiKQoKZ2dfY2x1c3RlckNvbXBhcmUgPC0gZ2dwbG90KGRhdGEgPSBwbG90ZGF0YSAsIG1hcHBpbmcgPSBhZXMoIHggPSBDbHVzdGVyICwgeSA9IERlc2NyaXB0aW9uICwgc2l6ZSA9IEdlbmVSYXRpbyAsIGNvbG9yID0gLWxvZzEwKHAuYWRqdXN0KSApICkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiYmx1ZSIgLCBoaWdoID0gInJlZCIgICwgYnJlYWtzID0gYygxLDEwLDIwLDMwLDQwLDUwLDYwKSAsIGxpbWl0cyA9IGMoMSw2MCkgKSArIAogIHRoZW1lX2J3KCkgKyAKICB0aGVtZSggYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsc2l6ZT0xMSksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLHNpemU9MTEsIGhqdXN0ID0gMSApICkKCmdnX2NsdXN0ZXJDb21wYXJlCmBgYAoKYGBge3IgZmlnLndpZHRoPTEwICwgZmlnLmFzcD0xLjV9CmdnX2NsdXN0ZXJDb21wYXJlX2NlbnRlciA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RkYXRhICwgbWFwcGluZyA9IGFlcyggeCA9IENsdXN0ZXIgLCB5ID0gRGVzY3JpcHRpb24gLCBzaXplID0gR2VuZVJhdGlvICwgY29sb3IgPSAtbG9nMTAocC5hZGp1c3QpICkgKSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJibHVlIiAsIGhpZ2ggPSAicmVkIiAgLCBicmVha3MgPSBjKDEsMTAsMjAsMzAsNDAsNTAsNjApICwgbGltaXRzID0gYygxLDYwKSApICsgCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIixzaXplPTExKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsc2l6ZT04LCBoanVzdCA9IDAuNSApICkKCmdnX2NsdXN0ZXJDb21wYXJlX2NlbnRlcgpgYGAKCiMgSGVhdG1hcCBvZiBETkEgZGFtYWdlIHJlc3BvbnNlIGdlbmVzCgpMb2FkIHRoZSBsaXN0IG9mIEROQSBkYW1hZ2UgcmVzcG9uc2UgZ2VuZXMuCgpgYGB7cn0KZG5hX2RhbWFnZV9nZW5lcyA8LSByZWFkLmNzdigiZ2VuZV9saXN0cy9ETkFfZGFtYWdlX2dlbmVzLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSApCmBgYAoKQ29udmVydCB0aGUgTW9kdWxlIGNvbHVtbiB0byBmYWN0b3IuCgpgYGB7cn0KZG5hX2RhbWFnZV9nZW5lcyRtb2R1bGUgPC0gYXMuZmFjdG9yKGRuYV9kYW1hZ2VfZ2VuZXMkbW9kdWxlKQpgYGAKCgpgYGB7cn0KZG5hX2RhbWFnZV9nZW5lcwpgYGAKCkdldCB0aGUgVFBNIGdlbmUgZXhwcmVzc2lvbiB2YWx1ZXMgZm9yIHRoZXNlIGdlbmVzIGZyb20gdGhlIFRQTSB0YWJsZQoKYGBge3J9ClRQTV9kbmFfZGFtYWdlX2dlbmVzIDwtIFRQTV9OU0NzICU+JSBkcGx5cjo6ZmlsdGVyKCBlbnNlbWJsX2dlbmVfaWQgJWluJSBkbmFfZGFtYWdlX2dlbmVzJGVuc2VtYmxfZ2VuZV9pZCAgKQpgYGAKCkNvbWJpbmUgdGhlIHR3byBkYXRhLmZyYW1lcwoKYGBge3J9ClRQTV9jb21iaW5lZCA8LSBsZWZ0X2pvaW4oeCA9IGRuYV9kYW1hZ2VfZ2VuZXMgLCB5ID0gVFBNX2RuYV9kYW1hZ2VfZ2VuZXMgLCBieSA9ICJlbnNlbWJsX2dlbmVfaWQiICkKYGBgCgpgYGB7cn0KaGVhZChUUE1fY29tYmluZWQpCmBgYAoKYGBge3J9CmNlbGxfb3JkZXIgPC0gcHNldWRvdGltZV9vcmRlcmluZyAlPiUgbXV0YXRlKCB0eXBlc29ydCA9IGFzLmNoYXJhY3RlcihmY3RfcmVjb2RlKC5mID0gdHlwZSAsIGMgPSAiYTEiICwgZCA9ICJhMiIgLCBhID0gInExIiAsIGIgPSAicTIiKSApICkgJT4lIGdyb3VwX2J5KGFnZSkgJT4lIGFycmFuZ2UoYWdlLCB0eXBlc29ydCkgJT4lIHB1bGwoY2VsbCkgJT4lIGFzLmNoYXJhY3RlcigpCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0yMH0KbGlicmFyeShwaGVhdG1hcCkKClRQTV9tYXQgPC0gYXMubWF0cml4KFRQTV9jb21iaW5lZCAlPiUgZHBseXI6OnNlbGVjdCggYyggImVuc2VtYmxfZ2VuZV9pZCIgLCBjZWxsX29yZGVyICkgKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJlbnNlbWJsX2dlbmVfaWQiKSkKClRQTV9tYXRfbmFtZXMgPC0gYXMubWF0cml4KFRQTV9jb21iaW5lZCAlPiUgZHBseXI6OnNlbGVjdCggYyggImdlbmVfc3ltYm9sIiAsIGNlbGxfb3JkZXIgKSApICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoImdlbmVfc3ltYm9sIikpCgphbm5vX3JvdyA8LSBkcGx5cjo6c2VsZWN0KGRuYV9kYW1hZ2VfZ2VuZXMgLCBtb2R1bGUgLCBlbnNlbWJsX2dlbmVfaWQgKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJlbnNlbWJsX2dlbmVfaWQiKQoKCmFubm9fY29sIDwtIE5TQ3NfYW5ub3RhdGlvbiAlPiUgZHBseXI6OnNlbGVjdCgtY2VsbCkKYGBgCgojIyAgUGxvdCBsb2cgdHJhbnNmb3JtZWQgVFBNIHZhbHVlcwoKYGBge3J9CnBoZWF0bWFwKAogIG1hdCA9IHBtaW4oIGxvZyggVFBNX21hdCArIDEgKSAsIDcgKSAsIAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFICwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UgLCAKICBzY2FsZSA9ICJub25lIiAsIAogIGJyZWFrcyA9IHNlcSgwLDcsbGVuZ3RoLm91dCA9IDEwMSkgLCAKICBjb2xvciA9IHZpcmlkaXNMaXRlOjp2aXJpZGlzKG4gPSAxMDApICwgCiAgYm9yZGVyX2NvbG9yID0gTkEgLCAKICAjIGdhcHNfcm93ID0gcm93X2JyZWFrc1tzZXFfbGVuKGxlbmd0aC5vdXQgPSBsZW5ndGgocm93X2JyZWFrcykgLSAxICldICwKICBhbm5vdGF0aW9uX2NvbCA9IGFubm9fY29sICwgCiAgYW5ub3RhdGlvbl9jb2xvcnMgPSBsaXN0KAogICAgICB0eXBlID0gYyhxMSA9ICJzdGVlbGJsdWUiICwgcTIgPSAic3RlZWxibHVlMSIgLCBhMSA9ICJ0b21hdG8iICwgYTIgPSAic2llbm5hMSIpLCAKICAgICAgYWdlID0gYyggeW91bmcgPSAieWVsbG93Z3JlZW4iICwgb2xkID0gInNsYXRlYmx1ZSIpCiAgICApCikKYGBgCgpEZXRlcm1pbmUgZ2FwcyBiZXR3ZWVuIGNhdGVnb3JpZXMKCmBgYHtyfQpyb3dfYnJlYWtzIDwtIGN1bXN1bSggYW5ub19yb3cgJT4lIGdyb3VwX2J5KG1vZHVsZSkgJT4lIG11dGF0ZSggbnVtID0gbGVuZ3RoKG1vZHVsZSkpICU+JSB1bmlxdWUoKSAlPiUgcHVsbChudW0pICkgCmBgYAoKUGxvdCBsb2cgdHJhbnNmb3JtZWQgVFBNIHZhbHVlcyB3aXRoIGdlbmUgbmFtZXMgYXMgcm93bmFtZXMKCmBgYHtyIGZpZy53aWR0aCA9IDEwICwgZmlnLmhlaWdodD0xNX0KYW5ub19jb2xfcmVuYW1lIDwtIGFubm9fY29sCgphbm5vX2NvbF9yZW5hbWUkdHlwZSA8LSBhcy5jaGFyYWN0ZXIoYW5ub19jb2xfcmVuYW1lJHR5cGUpCgphbm5vX2NvbF9yZW5hbWUkdHlwZVthbm5vX2NvbF9yZW5hbWUkdHlwZSA9PSAicTEiXSA8LSAicU5TQzEiCmFubm9fY29sX3JlbmFtZSR0eXBlW2Fubm9fY29sX3JlbmFtZSR0eXBlID09ICJxMiJdIDwtICJxTlNDMiIKYW5ub19jb2xfcmVuYW1lJHR5cGVbYW5ub19jb2xfcmVuYW1lJHR5cGUgPT0gImExIl0gPC0gImFOU0MxIgphbm5vX2NvbF9yZW5hbWUkdHlwZVthbm5vX2NvbF9yZW5hbWUkdHlwZSA9PSAiYTIiXSA8LSAiYU5TQzIiCgphbm5vX2NvbF9yZW5hbWUkdHlwZSA8LSBmYWN0b3IoeCA9IGFubm9fY29sX3JlbmFtZSR0eXBlICwgbGV2ZWxzID0gYygicU5TQzEiLCJxTlNDMiIsImFOU0MxIiwiYU5TQzIiKSApIApgYGAKCmBgYHtyIGZpZy53aWR0aCA9IDEwICwgZmlnLmhlaWdodD0xNX0Kc2NhbGVfd2hpdGVfcmVkIDwtIGNvbG9yUmFtcFBhbGV0dGUoY29sb3JzID0gYygid2hpdGUiLCJyZWQiKSkKCnBoZWF0bWFwKAogIG1hdCA9IHBtaW4oIGxvZyggVFBNX21hdF9uYW1lcyArIDEgKSAsIDggKSAsIAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFICwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UgLCAKICBzY2FsZSA9ICJub25lIiAsIAogIGJyZWFrcyA9IHNlcSgwLDgsbGVuZ3RoLm91dCA9IDEwMSkgLCAKICBjb2xvciA9IHNjYWxlX3doaXRlX3JlZChuID0gMTAwKSAsIAogIGFubm90YXRpb25fY29sID0gYW5ub19jb2xfcmVuYW1lICwgCiAgYW5ub3RhdGlvbl9jb2xvcnMgPSBsaXN0KAogICAgICB0eXBlID0gYyhxTlNDMSA9ICJzdGVlbGJsdWUiICwgcU5TQzIgPSAic3RlZWxibHVlMSIgLCBhTlNDMSA9ICJ0b21hdG8iICwgYU5TQzIgPSAic2llbm5hMSIpLCAKICAgICAgYWdlID0gYyggeW91bmcgPSAieWVsbG93Z3JlZW4iICwgb2xkID0gInNsYXRlYmx1ZSIpCiAgICApLAogIGdhcHNfY29sID0gMTMzLAogIHNob3dfY29sbmFtZXMgPSBGQUxTRSwgCiAgZm9udHNpemVfcm93ID0gNwopCmBgYAoKCiMgRGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGJldHdlZW4gb2xkIGFuZCB5b3VuZwoKIyMgREVTZXEyCgpgYGB7cn0KbGlicmFyeShERVNlcTIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KEJpb2NQYXJhbGxlbCkKYGBgCgoKUmVnaXN0ZXIgbnVtYmVyIG9mIGNvcmVzIGZvciBwYXJhbGxlbCBleGVjdXRpb24KYGBge3J9CnJlZ2lzdGVyKEJQUEFSQU0gPSAgTXVsdGljb3JlUGFyYW0od29ya2VycyA9IDQpICwgZGVmYXVsdCA9IFRSVUUpCmBgYAoKCiMjIyBMb2FkIHRoZSByYXcgY291bnRzIGZvciBhbGwgdGhlIGNlbGxzCmBgYHtyfQpjb3VudERhdGEgPC0gcmVhZC5jc3YoZmlsZSA9ICJjb3VudF90YWJsZS9yYXdfY291bnRzX05TQ3NfU01BUlRzZXEyLmNzdiIgLCBoZWFkZXIgPSBUUlVFICwgcm93Lm5hbWVzID0gMSkKYGBgCgoKQW5kIHdlIGxvYWQgdGhlIGNlbGwgYW5ub3RhdGlvbi4KYGBge3J9CmNvbERhdGEgPC0gTlNDc19hbm5vdGF0aW9uCgpjb2xEYXRhJHR5cGVfc2F2ZSA8LSBjb2xEYXRhJHR5cGUKCmxldmVscyhjb2xEYXRhJHR5cGUpIDwtIGMoImFOU0MxIiwiYU5TQzIiLCJxTlNDMSIsInFOU0MyIikKYGBgCgpgYGB7cn0KY29tcGFyaXNvbnMgPC0gbGlzdCggYU5TQyA9IGMoImFOU0MxIiwiYU5TQzIiKSAsIHFOU0MgPSBjKCJxTlNDMSIsInFOU0MyIikgLCBOU0MgPSBjKCJxTlNDMSIsInFOU0MyIiwiYU5TQzEiLCJhTlNDMiIpICwgcU5TQzEgPSBjKCJxTlNDMSIpICxxTlNDMiA9IGMoInFOU0MyIiksIGFOU0MxID0gYygiYU5TQzEiKSwgYU5TQzIgPSBjKCJhTlNDMiIpICkKYGBgCgoKTm93IHdlIHdhbnQgdG8gc2VlIGlmIGFsbCBvdXIgY2VsbHMgYXZhaWxhYmxlIGluIHRoZSBjb2xEYXRhIGFyZSBhbHNvIGZvdW5kIGluIHRoZSBjb3VudERhdGEgdGFibGU/CmBgYHtyfQphbGwoY29sRGF0YSRjZWxsICVpbiUgY29sbmFtZXMoY291bnREYXRhKSkKYGBgCgpBbmQgaWYgdGhlaXIgb3JkZXIgaXMgdGhlIHNhbWU/CmBgYHtyfQphbGwoY29sRGF0YSRjZWxsID09IGNvbG5hbWVzKGNvdW50RGF0YSlbLTFdKQpgYGAKCkdyZWF0LCB0aHVzIHdlIGNhbiBwcm9jZWVkIGFuZCBzZXQgdXAgb3VyIERFU2VxMiBvYmplY3RzIGluIGEgbGlzdC4KClRoZSBjb21wYXJpc29ucyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhcmU6CgotIGFOU0M6ICAgICBvbGQgdnMgeW91bmcKLSBxTlNDOiAgICAgb2xkIHZzIHlvdW5nCi0gYWxsIE5TQ3M6IG9sZCB2cyB5b3VuZwotIGluZGl2aWR1YWwgY2VsbHR5cGVzOiBvbGQgdnMgeW91bmcKClJlbmFtZSB0aGUgZ2VuZSBjb2x1bW4KYGBge3J9CmNvdW50RGF0YSA8LSBkcGx5cjo6cmVuYW1lKCBjb3VudERhdGEgLCAgZ2VuZSA9IGVuc2VtYmxfZ2VuZV9pZCApCmBgYAoKIyMjIFN1YnNldCB0aGUgZGF0YSBmcm9tIGNvbERhdGEgYW5kIGNvdW50RGF0YSBhY2NvcmRpbmcgdG8gdGhlIGNlbGx0eXBlcyBpbnRvIGEgbGlzdApgYGB7cn0KY2VsbHR5cGVfZGF0YV9saXN0IDwtIGxhcHBseSgKICAKICBYID0gIGNvbXBhcmlzb25zICwgCiAgCiAgRlVOID0gZnVuY3Rpb24oeCl7CiAgICBjb2xEIDwtIGRwbHlyOjpmaWx0ZXIoIGNvbERhdGEgLCAgdHlwZSAlaW4lIHggKQogICAgCiAgICBjZWxsX2lkcyA8LSBjb2xEJGNlbGwKICAgIAogICAgY291bnREIDwtIGRwbHlyOjpzZWxlY3QoIGNvdW50RGF0YSAsIG9uZV9vZiggImdlbmUiICwgYXMuY2hhcmFjdGVyKGNlbGxfaWRzKSAgKSkKICAgIAogICAgbGlzdCggY29sRGF0YSA9IGNvbEQgLCBjb3VudERhdGEgPSBjb3VudEQgKQogIH0KKQpgYGAKCgojIyMjIENoZWNrIHRoZSBvcmRlciBvZiB0aGUgY2VsbHR5cGVzIGluIHRoZSBsaXN0CmBgYHtyfQpjZWxsdHlwZV9vcmRlciA8LSBsYXBwbHkoCiAgWCA9IGNlbGx0eXBlX2RhdGFfbGlzdCAsIAogIEZVTiA9IGZ1bmN0aW9uKHgpeyBhcy5jaGFyYWN0ZXIoIHVuaXF1ZSggeCRjb2xEYXRhJHR5cGUgKSApIH0KKQoKY2VsbHR5cGVfb3JkZXIKYGBgCgoKIyMjIFByZXBhcmUgREVTZXEgb2JqZWN0cwpNYWtlIGEgbGlzdCBvZiBERVNlcURhdGFTZXRzIC0gb25lIGZvciBlYWNoIGNlbGx0eXBlCk9ubHkga2VlcCBleHByZXNzZWQgZ2VuZXMgaW4gdGhlIGRhdGEgc2V0cwpTZXQgInlvdW5nIiBhcyBiYXNlIGxldmVsIGZvciBjb21wYXJpc29uOiAKICBUaHVzIGEgRkMgPiAwIHdpbGwgbWVhbiBpdCBpcyBoaWdoZXIgaW4gdGhlIG9sZCBjZWxscwogIApCZWNhdXNlIHdlIGhhdmUgZXhwZWN0ZWQgcmVhZHMgZnJvbSB0aGUgUlNFTSBvdXRwdXQsIHdlIG5lZWQgdG8gcm91bmQgdGhlIHZhbHVlcyB0byBpbnRlZ2VyLCBhcyBERVNlcTIgZXhwZWN0cyBpbnRlZ2VyIHZhbHVlcwoKYGBge3IgbWFrZURFU0VxMm9iamVjdH0KY2VsbHR5cGVfZGF0YV9saXN0IDwtIGxhcHBseSgKICAKICBYID0gY2VsbHR5cGVfZGF0YV9saXN0ICwgCiAgCiAgRlVOID0gZnVuY3Rpb24oeCl7CiAgICByb3duYW1lcyh4JGNvdW50RGF0YSkgPC0gTlVMTAogICAgcm93bmFtZXMoeCRjb2xEYXRhKSA8LSBOVUxMCiAgICAKICAgIGRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKGNvbHVtbl90b19yb3duYW1lcyggZGYgPSB4JGNvdW50RGF0YSAsIHZhciA9ICJnZW5lIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gY29sdW1uX3RvX3Jvd25hbWVzKCBkZiA9IHgkY29sRGF0YSAsIHZhciA9ICJjZWxsIiApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IGFnZSApCiAgICAKICAgIGRkcyA8LSBkZHNbIHJvd1N1bXMoY291bnRzKGRkcykpID4gMSwgXQogICAgZGRzJGFnZSA8LSByZWxldmVsKHggPSBkZHMkYWdlICwgcmVmID0gInlvdW5nIikKICAgIAogICAgZGRzCiAgfQopCmBgYAoKIyMjIFJ1biBERVNlcQpSdW4gREVTZXEgb24gdGhlIGxpc3Qgb2YgZGRzIG9iamVjdHMgLSB3aWxsIGJlIHBhcmFsbGVseSBydW4gb24gdGhlIG51bWJlciBvZiBjb3JlcyBzZXQgaW4gdGhlIHN0YXJ0IG9mIHRoaXMgZmlsZSBieSByZWdpc3RlcigpIC4uLgpgYGB7ciBydW5ERVNlcTJ9Cmxvb3BudW0gPSAwCgpjZWxsdHlwZV9kYXRhX2xpc3QgPC0gbGFwcGx5KAogIAogIFggPSBjZWxsdHlwZV9kYXRhX2xpc3QgLCAKICAKICBGVU4gPSBmdW5jdGlvbihkZHMpewogICAgCiAgICBsb29wbnVtIDw8LSBsb29wbnVtICsgMSAKICAgIAogICAgcHJpbnQocGFzdGUoIlJ1bm5pbmcgREVTZXEgZm9yIGZpZWxkOiIsIGxvb3BudW0gKSApCiAgICAKICAgIERFU2VxKG9iamVjdCA9IGRkcyAsIHBhcmFsbGVsID0gVFJVRSApCiAgCiAgfQopCmBgYAoKCiMjIyBFeHRyYWN0IHRoZSByZXN1bHRzIGZyb20gdGhlIERFU2VxMiBkYXRhIHNldHMKYGBge3IgZXh0cmFjdFJlc3VsdHN9Cmxvb3BudW0gPSAwCgpyZXN1bHRzX2xpc3QgPC0gbGFwcGx5KAogIAogIFggPSBjZWxsdHlwZV9kYXRhX2xpc3QgLCAKICAKICBGVU4gPSBmdW5jdGlvbihkZHMpewoKICAgIGxvb3BudW0gPDwtIGxvb3BudW0gKyAxIAogICAgCiAgICBwcmludChwYXN0ZSgiRXh0cmFjdCByZXN1bHRzIGZvciBmaWVsZDoiLCBsb29wbnVtICkgKQoKICAgIERFU2VxMjo6cmVzdWx0cyhvYmplY3QgPSBkZHMgLCB0aWR5ID0gVFJVRSAsIHBhcmFsbGVsID0gVFJVRSApICAKICAKICB9CikKYGBgCgoKIyMjIyBTYXZlIHRoZSBERVNlcTIgZGF0YSBzZXRzIGxpc3QgYW5kIHRoZSByZXN1bHRzIGxpc3QgYXMgUkRTIGZpbGVzCmBgYHtyfQpzYXZlUkRTKG9iamVjdCA9IHJlc3VsdHNfbGlzdCAsIGZpbGUgPSAicmVzdWx0cy9ERV9ERVNlcTJfb2xkX3ZzX3lvdW5nL3Jlc3VsdHNfbGlzdC5SRFMiKQpzYXZlUkRTKG9iamVjdCA9IGNlbGx0eXBlX2RhdGFfbGlzdCAsIGZpbGUgPSAicmVzdWx0cy9ERV9ERVNlcTJfb2xkX3ZzX3lvdW5nL0RFU2VxMl9jZWxsdHlwZV9kYXRhX2xpc3QuUkRTIikKYGBgCgoKIyMjIyBFeHRyYWN0IHRoZSBpbmRpdmlkdWFsIERFIHRhYmxlcyBmcm9tIHRoZSBsaXN0IGFuZCBzYXZlIHRoZW0gaW5kaXZpZHVhbGx5IGFzIGNzdiBmaWxlcwpgYGB7cn0Kd3JpdGUuY3N2KCB4ID0gcmVzdWx0c19saXN0W1sxXV0gLCBmaWxlID0gcGFzdGUwKCJyZXN1bHRzL0RFX0RFU2VxMl9vbGRfdnNfeW91bmcvIiAsICJERVNlcTJfcmVzdWx0XyIgLCBuYW1lcyhjb21wYXJpc29ucylbWzFdXSAsICIuY3N2IiApICkKd3JpdGUuY3N2KCB4ID0gcmVzdWx0c19saXN0W1syXV0gLCBmaWxlID0gcGFzdGUwKCJyZXN1bHRzL0RFX0RFU2VxMl9vbGRfdnNfeW91bmcvIiAsICJERVNlcTJfcmVzdWx0XyIgLCBuYW1lcyhjb21wYXJpc29ucylbWzJdXSAsICIuY3N2IiAgICkgKQp3cml0ZS5jc3YoIHggPSByZXN1bHRzX2xpc3RbWzNdXSAsIGZpbGUgPSBwYXN0ZTAoInJlc3VsdHMvREVfREVTZXEyX29sZF92c195b3VuZy8iICwgIkRFU2VxMl9yZXN1bHRfIiAsIG5hbWVzKGNvbXBhcmlzb25zKVtbM11dICwgIi5jc3YiICAgKSApCndyaXRlLmNzdiggeCA9IHJlc3VsdHNfbGlzdFtbNF1dICwgZmlsZSA9IHBhc3RlMCgicmVzdWx0cy9ERV9ERVNlcTJfb2xkX3ZzX3lvdW5nLyIgLCAiREVTZXEyX3Jlc3VsdF8iICwgbmFtZXMoY29tcGFyaXNvbnMpW1s0XV0gLCAiLmNzdiIgICApICkKd3JpdGUuY3N2KCB4ID0gcmVzdWx0c19saXN0W1s1XV0gLCBmaWxlID0gcGFzdGUwKCJyZXN1bHRzL0RFX0RFU2VxMl9vbGRfdnNfeW91bmcvIiAsICJERVNlcTJfcmVzdWx0XyIgLCBuYW1lcyhjb21wYXJpc29ucylbWzVdXSAsICIuY3N2IiAgICkgKQp3cml0ZS5jc3YoIHggPSByZXN1bHRzX2xpc3RbWzZdXSAsIGZpbGUgPSBwYXN0ZTAoInJlc3VsdHMvREVfREVTZXEyX29sZF92c195b3VuZy8iICwgIkRFU2VxMl9yZXN1bHRfIiAsIG5hbWVzKGNvbXBhcmlzb25zKVtbNl1dICwgIi5jc3YiICAgKSApCndyaXRlLmNzdiggeCA9IHJlc3VsdHNfbGlzdFtbN11dICwgZmlsZSA9IHBhc3RlMCgicmVzdWx0cy9ERV9ERVNlcTJfb2xkX3ZzX3lvdW5nLyIgLCAiREVTZXEyX3Jlc3VsdF8iICwgbmFtZXMoY29tcGFyaXNvbnMpW1s3XV0gLCAiLmNzdiIgICApICkKYGBgCgoKIyMgdC1UZXN0CgojIyMgTlNDcwoKYGBge3J9CiMgTG9hZCB0aGUgVFBNIGV4cHJlc3Npb24gdmFsdWVzIGZvciB0aGUgU01BUlRzZXEyIGRhdGEKVFBNX05TQyA8LSByZW1vdmVfcm93bmFtZXMoZGYgPSBUUE1fTlNDcykgJT4lIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiZW5zZW1ibF9nZW5lX2lkIiApCgojIExvYWQgdGhlIGNlbGwgYW5ub3RhdGlvbgpOU0NfYW5ubyA8LSBOU0NzX2Fubm90YXRpb24KCiMgU3Vic2V0IHRoZSBleHByZXNzaW9uIG1hdHJpeCBmb3IgeW91bmcgYW5kIG9sZCBpbnRvIGRpZmZlcmVudCBtYXRyaWNlcwpUUE1fb2xkIDwtIFRQTV9OU0NbYXMuY2hhcmFjdGVyKE5TQ19hbm5vW05TQ19hbm5vJGFnZSA9PSAib2xkIixdJGNlbGwpXQpUUE1feW91bmcgPC0gVFBNX05TQ1thcy5jaGFyYWN0ZXIoTlNDX2Fubm9bTlNDX2Fubm8kYWdlID09ICJ5b3VuZyIsXSRjZWxsKV0KCiMgTG9nIHRyYW5zZm9ybSB0aGUgZXhwcmVzc2lvbiB2YWx1ZXMgClRQTV9vbGQgPC0gbG9nKFRQTV9vbGQrMSkKVFBNX3lvdW5nIDwtIGxvZyhUUE1feW91bmcrMSkKClRQTV9OU0MgPC0gYXMubWF0cml4KCBsb2coVFBNX05TQysxKSApCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDYWxjdWxhdGUgdGhlIG1lYW4gZXhwcmVzc2lvbiwgc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCBudW1iZXIgb2YgY2VsbHMgd2l0aCAwIGNvdW50cyBmb3IgZWFjaCByb3cgKGdlbmUpIGZvciB5b3VuZyBhbmQgb2xkIGNlbGxzIHNlcGFyYXRlbHkKCnRhYmxlX3NtczIgPC0gZGF0YS5mcmFtZSggCiAgZW5zZW1ibF9nZW5lX2lkID0gcm93bmFtZXMoVFBNX3lvdW5nKSwKICBhdmdfbG9nVFBNX3lvdW5nID0gYXBwbHkoVFBNX3lvdW5nICwgTUFSR0lOID0gMSAsIEZVTiA9IG1lYW4pICAsIAogIGF2Z19sb2dUUE1fb2xkID0gYXBwbHkoVFBNX29sZCAsIE1BUkdJTiA9IDEgLCBGVU4gPSBtZWFuKSAgLAogIGF2Z19sb2dUUE0gPSBhcHBseShUUE1fTlNDICwgTUFSR0lOID0gMSAsIEZVTiA9IG1lYW4pICwKICBzZF9sb2dUUE1feW91bmcgPSBhcHBseShUUE1feW91bmcgLCBNQVJHSU4gPSAxICwgRlVOID0gc2QpICAsCiAgc2RfbG9nVFBNX29sZCA9IGFwcGx5KFRQTV9vbGQgLCBNQVJHSU4gPSAxICwgRlVOID0gc2QpLAogIGZyYWN0aW9uX2NlbGxzX3plcm9feW91bmcgPSBhcHBseShUUE1feW91bmcgPT0gMCAsIE1BUkdJTiA9IDEgLCBGVU4gPSBzdW0pL2xlbmd0aChUUE1feW91bmcpLAogIGZyYWN0aW9uX2NlbGxzX3plcm9fb2xkID0gYXBwbHkoVFBNX29sZCA9PSAwICwgTUFSR0lOID0gMSAsIEZVTiA9IHN1bSkvbGVuZ3RoKFRQTV9vbGQpCikKCiMgQ2FsY3VsYXRlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gZnJvbSBvbGQgYW5kIHlvdW5nIChvbGQgLSB5b3VuZykKdGFibGVfc21zMiRkaWZmZXJlbmNlX29mX2F2ZyA8LSAodGFibGVfc21zMiRhdmdfbG9nVFBNX29sZCAtIHRhYmxlX3NtczIkYXZnX2xvZ1RQTV95b3VuZyApCgojIENhbGN1bGF0ZSB0aGUgbWVhbiBTdGFuZGFyZCBEZXZpYXRpb24gYmV0d2VlbiB5b3VuZyBhbmQgb2xkCnRhYmxlX3NtczIkbWVhbl9zZCA8LSBhcHBseSggWCA9ICB0YWJsZV9zbXMyWyxjKCJzZF9sb2dUUE1feW91bmciLCJzZF9sb2dUUE1fb2xkIildICwgTUFSR0lOID0gMSAsIEZVTiA9IG1lYW4pCgojIEZpbmFsbHkgY2FsY3VsYXRlIENvaGVucyBELCBieSBkZXZpZGluZyB0aGUgZGlmZmVyZW5jZSBvZiB0aGUgbWVhbiB2YWx1ZXMgYnkgdGhlIG1lYW4gc3RhbmRhcmQgZGV2aWF0aW9uIAp0YWJsZV9zbXMyJCdkaWZmZXJlbmNlX29mX2F2Zy9tZWFuX3NkJyAgPC0gdGFibGVfc21zMiRkaWZmZXJlbmNlX29mX2F2Zy90YWJsZV9zbXMyJG1lYW5fc2QKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQWRkIHAtdmFsdWVzIGZyb20gdC10ZXN0CgojIFJ1biB0LXRlc3Qgb24gU01BUlRzZXEyIE5TQyBkYXRhIG9sZCBhbmQgeW91bmcKbGlicmFyeShnZW5lZmlsdGVyKQoKIyBQcmVwYXJlIGZhY3RvciB3aXRoIHlvdW5nIGFuZCBvbGQgaW4gb3JkZXIgb2YgdGhlIGNvbHVtbiBuYW1lcwpmYWN0IDwtIGFzLmNoYXJhY3RlciggY29sbmFtZXMoVFBNX05TQykgKQpmYWN0WyBncmVwbCh4ID0gZmFjdCAsIHBhdHRlcm4gPSAic19kb3QiKSBdIDwtICJvbGQiCmZhY3RbIGdyZXBsKHggPSBmYWN0ICwgcGF0dGVybiA9ICJeTiIgKSBdIDwtICJ5b3VuZyIKZmFjdCA8LSBmYWN0b3IoIGZhY3QgKQoKCiMgUHJlcGFyZSBtYXRyaXggZm9yIHQtdGVzdCBpbnB1dApUUE1fTlNDX21hdCA8LSBUUE1fTlNDClRQTV9OU0NfbWF0IDwtIGFzLm1hdHJpeCggVFBNX05TQ19tYXQgKSAKCiMgUnVuIHQtdGVzdCB3aXRoIHJvd3R0ZXN0cyBmdW5jdGlvbiBmcm9tIGdlbmVmaWx0ZXIgcGFja2FnZXMKdF90ZXN0X05TQ3NfU01BUlRzZXEyIDwtIHJvd3R0ZXN0cyh4ID0gVFBNX05TQ19tYXQgLCBmYWMgPSBmYWN0ICkKCiMgQWRkIGVuc2VtYmxfZ2VuZV9pZCBhcyBjb2x1bW4gZnJvbSB0aGUgcm93bmFtZXMKdF90ZXN0X05TQ3NfU01BUlRzZXEyJGVuc2VtYmxfZ2VuZV9pZCA8LSByb3duYW1lcyh0X3Rlc3RfTlNDc19TTUFSVHNlcTIpIAoKIyBKb2luIHRoZSB0YWJsZXMKdGFibGVfc21zMl9tZXJnZWRfd2l0aF90dGVzdCA8LSBmdWxsX2pvaW4oeCA9IHRhYmxlX3NtczIgLCB5ID0gdF90ZXN0X05TQ3NfU01BUlRzZXEyICwgYnkgPSAiZW5zZW1ibF9nZW5lX2lkIiApCgp0YWJsZV9zbXMyX21lcmdlZF93aXRoX3R0ZXN0IDwtIGFycmFuZ2UodGFibGVfc21zMl9tZXJnZWRfd2l0aF90dGVzdCAsIGRlc2MoZGlmZmVyZW5jZV9vZl9hdmcvbWVhbl9zZCkpCgojIyBTYXZlIHRoZSByZXN1bHRzIGFzIGEgY3N2IGZpbGUKIyB3cml0ZS5jc3YoeCA9IHRhYmxlX3NtczJfbWVyZ2VkX3dpdGhfdHRlc3QgLCBmaWxlID0gIkRFX3Jlc3VsdHMvREVfTlNDX1NtYXJ0U2VxMi9ERV9OU0NzX1NtYXJ0U2VxMl90LXRlc3RfQ29oZW5zRC5jc3YiICkKYGBgCgojIyMjIEV4cHJlc3Npb24gb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGZyb20gQnVsayBOU0NzCgpgYGB7cn0KIyBMb2FkIGJ1bGsgTlNDcyBERSBnZW5lcyBiZXR3ZWVuIG9sZCBhbmQgeW91bmcgYW5pbWFscwpidWxrX0RFX3Jlc3VsdHMgPC0gcmVhZC5jc3YoIi4uL0J1bGtfc2VxdWVuY2luZy9ERVNlcTJfcmVzdWx0c19vbGRfdnNfeW91bmcvR1BfREVTZXEyX3Jlc3VsdHNfT2xkX3ZzX1lhbmcuY3N2IiAsIHJvdy5uYW1lcyA9IDEpCgojIE1lcmdlIHRoZSB0YWJsZSBvZiBjYWxjdWxhdGVkIHZhbHVlcyB3aXRoIHRoZSBERVNlcTIgb3V0cHV0IG9mIHRoZSBidWxrIE5TQyBjb21wYXJpc29uIG9sZCB2cyB5b3VuZyBieSBlbnNlbWJsX2dlbmVfaWQKdGFibGVzX3NtczJfbWVyZ2VkIDwtIGZ1bGxfam9pbih4ID0gdGFibGVfc21zMiAsIHkgPSBidWxrX0RFX3Jlc3VsdHMpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBQbG90IHRoZSBkaWZmZXJlbmNlIGluIG1lYW4gZXhwcmVzc2lvbiB2ZXJzdXMgdGhlIHBhcmFsbGVsIG1heGltdW0gb2YgemVyby1jb3VudCBjZWxsIHBlcmNlbnRhZ2UKdGFibGVzX3NtczJfbWVyZ2VkICU+JSAKICBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JQogIGdncGxvdCggYWVzKAogICAgeCA9IHBtYXgoIGZyYWN0aW9uX2NlbGxzX3plcm9fb2xkICwgZnJhY3Rpb25fY2VsbHNfemVyb195b3VuZyApICAsIAogICAgeSA9IGF2Z19sb2dUUE1fb2xkIC0gYXZnX2xvZ1RQTV95b3VuZyAsIAogICAgY29sb3IgPSBmYWN0b3Ioc2lnbihsb2cyRm9sZENoYW5nZSkpCiAgICApKSArIGdlb21fcG9pbnQoKQoKIyBTYW1lIHBsb3Qgd2l0aCBibHVlICh1cCkgYW5kIHJlZCAoZG93bikgY29sb3JlZCBwb2ludHMgYW5kIGF4ZXMgbGFiZWxzCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShjb3dwbG90KQoKYXNfdGliYmxlKHRhYmxlc19zbXMyX21lcmdlZCkgJT4lCiAgICBmaWx0ZXIoIHBhZGogPCAwLjA1KSAlPiUKICAgIG11dGF0ZSggY29sID0gY2FzZV93aGVuKAogICAgICBwYWRqID4gMC4wNSB+ICJuLnMuIiAsIAogICAgICBsb2cyRm9sZENoYW5nZSA+IDAuMyB+ICJ1cCIsCiAgICAgIGxvZzJGb2xkQ2hhbmdlIDwgLTAuMyB+ICJkb3duIiwKICAgICAgVFJVRSB+ICJuLnMuIiApICkgJT4lIAogICAgZ2dwbG90KCBhZXMoCiAgICAgIHggPSBwbWF4KCBmcmFjdGlvbl9jZWxsc196ZXJvX29sZCAsIGZyYWN0aW9uX2NlbGxzX3plcm9feW91bmcgKSAgLCAKICAgICAgeSA9IGF2Z19sb2dUUE1fb2xkIC0gYXZnX2xvZ1RQTV95b3VuZyAsIAogICAgICBjb2xvciA9IGNvbCAKICAgICkpICsgCiAgICBnZW9tX3BvaW50KCkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCAsIGNvbG9yID0gImdyZXk0MCIpICsKICAgIHhsYWIoIk1heC4gcGVyY2VudGFnZSBvZiBjZWxscyB3aXRoIG5vIHJlYWRzIHBlciBnZW5lIGluIG9sZCBvciB5b3VuZyIpICsKICAgIHlsYWIoIkRpZmZlcmVuY2Ugb2YgYXZnLiBsb2coVFBNKzEpIFxuIGJldHdlZW4gb2xkIGFuZCB5b3VuZyIpICsKICAgIHRoZW1lX2Nvd3Bsb3QoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXk4MCIpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwoIG5hbWUgPSAiRGlyZWN0aW9uIG9mIGNoYW5nZSBpbiBidWxrIiAsIHZhbHVlcyA9IGMoZG93biA9ICJyZWQiICwgdXAgPSAiYmx1ZSIpKSAKICAgIAojIC0tPiBleHBvcnRlZCB0byBQREYgNng5IGluY2hlcyBhbmQgNHg5ICh3aWRlKQoKCmBgYAoKCiMjIyBpbmRpdmlkdWFsIHN1YnBvcHVsYXRpb25zCgpgYGB7cn0KIyBMb2FkIHRoZSBUUE0gZXhwcmVzc2lvbiB2YWx1ZXMgZm9yIHRoZSBTTUFSVHNlcTIgZGF0YQpUUE1fTlNDIDwtIHJlbW92ZV9yb3duYW1lcyhkZiA9IFRQTV9OU0NzKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCB2YXIgPSAiZW5zZW1ibF9nZW5lX2lkIiApCgojIExvYWQgdGhlIGNlbGwgYW5ub3RhdGlvbgpOU0NfYW5ubyA8LSBOU0NzX2Fubm90YXRpb24gCk5TQ19hbm5vJHR5cGUgPC0gcmVjb2RlX2ZhY3RvciggTlNDX2Fubm8kdHlwZSAsIHExID0gInFOU0MxIiwgcTIgPSAicU5TQzIiLCBhMSA9ICJhTlNDMSIgLCBhMiA9ICJhTlNDMiIgKQoKIyBTdWJzZXQgdGhlIGV4cHJlc3Npb24gbWF0cml4IGZvciB5b3VuZyBhbmQgb2xkIGludG8gZGlmZmVyZW50IG1hdHJpY2VzClRQTV9vbGQgPC0gVFBNX05TQ1thcy5jaGFyYWN0ZXIoTlNDX2Fubm9bTlNDX2Fubm8kYWdlID09ICJvbGQiLF0kY2VsbCldClRQTV95b3VuZyA8LSBUUE1fTlNDW2FzLmNoYXJhY3RlcihOU0NfYW5ub1tOU0NfYW5ubyRhZ2UgPT0gInlvdW5nIixdJGNlbGwpXQoKIyBMb2cgdHJhbnNmb3JtIHRoZSBleHByZXNzaW9uIHZhbHVlcyAKVFBNX29sZCA8LSBsb2coVFBNX29sZCsxKQpUUE1feW91bmcgPC0gbG9nKFRQTV95b3VuZysxKQoKVFBNX05TQyA8LSBhcy5tYXRyaXgoIGxvZyhUUE1fTlNDKzEpICkKCgpOU0NfYW5ub195b3VuZyA8LSBOU0NfYW5ub1tOU0NfYW5ubyRhZ2UgPT0gInlvdW5nIixdCk5TQ19hbm5vX29sZCA8LSBOU0NfYW5ub1tOU0NfYW5ubyRhZ2UgPT0gIm9sZCIsXQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgRnVuY3Rpb24gdGhhdCBwZXJmb3JtIGNhbGN1bGF0aW9uIG9mIApydW5fdHRlc3RfYW5kX2NhbGN1bGF0ZV9Db2hlbnNfZCA8LSBmdW5jdGlvbihzdWJwb3ApewoKICAgICMjIFN1YnNldCBjZWxscyBmb3IgaW5kaXZpZHVhbCBzdWJwb3B1bGF0aW9ucwogICAgVFBNX3lvdW5nX3N1YnBvcCA8LSBUUE1feW91bmdbYXMuY2hhcmFjdGVyKE5TQ19hbm5vX3lvdW5nW05TQ19hbm5vX3lvdW5nJHR5cGUgPT0gc3VicG9wLF0kY2VsbCldCiAgICBUUE1fb2xkX3N1YnBvcCA8LSBUUE1fb2xkW2FzLmNoYXJhY3RlcihOU0NfYW5ub19vbGRbTlNDX2Fubm9fb2xkJHR5cGUgPT0gc3VicG9wLF0kY2VsbCldCiAgICBUUE1fTlNDX3N1YnBvcCA8LSBUUE1fTlNDWyxhcy5jaGFyYWN0ZXIoTlNDX2Fubm9bTlNDX2Fubm8kdHlwZSA9PSBzdWJwb3AsXSRjZWxsKV0KICAKICAgICMgQ2FsY3VsYXRlIHRoZSBtZWFuIGV4cHJlc3Npb24sIHN0YW5kYXJkIGRldmlhdGlvbiBhbmQgbnVtYmVyIG9mIGNlbGxzIHdpdGggMCBjb3VudHMgZm9yIGVhY2ggcm93IChnZW5lKSBmb3IgeW91bmcgYW5kIG9sZCBjZWxscyBzZXBhcmF0ZWx5CiAgICB0YWJsZV9zbXMyIDwtIGRhdGEuZnJhbWUoIAogICAgICBlbnNlbWJsX2dlbmVfaWQgPSByb3duYW1lcyhUUE1feW91bmdfc3VicG9wKSwKICAgICAgYXZnX2xvZ1RQTV95b3VuZyA9IGFwcGx5KFRQTV95b3VuZ19zdWJwb3AgLCBNQVJHSU4gPSAxICwgRlVOID0gbWVhbikgICwgCiAgICAgIGF2Z19sb2dUUE1fb2xkID0gYXBwbHkoVFBNX29sZF9zdWJwb3AgLCBNQVJHSU4gPSAxICwgRlVOID0gbWVhbikgICwKICAgICAgc2RfbG9nVFBNX3lvdW5nID0gYXBwbHkoVFBNX3lvdW5nX3N1YnBvcCAsIE1BUkdJTiA9IDEgLCBGVU4gPSBzZCkgICwKICAgICAgc2RfbG9nVFBNX29sZCA9IGFwcGx5KFRQTV9vbGRfc3VicG9wICwgTUFSR0lOID0gMSAsIEZVTiA9IHNkKSwKICAgICAgZnJhY3Rpb25fY2VsbHNfemVyb195b3VuZyA9IGFwcGx5KFRQTV95b3VuZ19zdWJwb3AgPT0gMCAsIE1BUkdJTiA9IDEgLCBGVU4gPSBzdW0pL2xlbmd0aChUUE1feW91bmdfc3VicG9wKSwKICAgICAgZnJhY3Rpb25fY2VsbHNfemVyb19vbGQgPSBhcHBseShUUE1fb2xkX3N1YnBvcCA9PSAwICwgTUFSR0lOID0gMSAsIEZVTiA9IHN1bSkvbGVuZ3RoKFRQTV9vbGRfc3VicG9wKQogICAgKQogICAgCiAgICAjIENhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtZWFuIGZyb20gb2xkIGFuZCB5b3VuZyAob2xkIC0geW91bmcpCiAgICB0YWJsZV9zbXMyJGRpZmZlcmVuY2Vfb2ZfYXZnIDwtICh0YWJsZV9zbXMyJGF2Z19sb2dUUE1fb2xkIC0gdGFibGVfc21zMiRhdmdfbG9nVFBNX3lvdW5nICkKICAgIAogICAgIyBDYWxjdWxhdGUgdGhlIG1lYW4gU3RhbmRhcmQgRGV2aWF0aW9uIGJldHdlZW4geW91bmcgYW5kIG9sZAogICAgdGFibGVfc21zMiRtZWFuX3NkIDwtIGFwcGx5KCBYID0gIHRhYmxlX3NtczJbLGMoInNkX2xvZ1RQTV95b3VuZyIsInNkX2xvZ1RQTV9vbGQiKV0gLCBNQVJHSU4gPSAxICwgRlVOID0gbWVhbikKICAgIAogICAgIyBGaW5hbGx5IGNhbGN1bGF0ZSBDb2hlbnMgRCwgYnkgZGV2aWRpbmcgdGhlIGRpZmZlcmVuY2Ugb2YgdGhlIG1lYW4gdmFsdWVzIGJ5IHRoZSBtZWFuIHN0YW5kYXJkIGRldmlhdGlvbiAKICAgIHRhYmxlX3NtczIkJ2RpZmZlcmVuY2Vfb2ZfYXZnL21lYW5fc2QnIDwtIHRhYmxlX3NtczIkZGlmZmVyZW5jZV9vZl9hdmcvdGFibGVfc21zMiRtZWFuX3NkCiAgICAKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAjIEFkZCBwLXZhbHVlcyBmcm9tIHQtdGVzdAogICAgCiAgICAjIFJ1biB0LXRlc3Qgb24gU01BUlRzZXEyIE5TQyBkYXRhIG9sZCBhbmQgeW91bmcKICAgIAogICAgIyBQcmVwYXJlIGZhY3RvciB3aXRoIHlvdW5nIGFuZCBvbGQgaW4gb3JkZXIgb2YgdGhlIGNvbHVtbiBuYW1lcwogICAgZmFjdCA8LSBhcy5jaGFyYWN0ZXIoIGNvbG5hbWVzKFRQTV9OU0Nfc3VicG9wKSApCiAgICBmYWN0WyBncmVwbCh4ID0gZmFjdCAsIHBhdHRlcm4gPSAic19kb3QiKSBdIDwtICJvbGQiCiAgICBmYWN0WyBncmVwbCh4ID0gZmFjdCAsIHBhdHRlcm4gPSAiXk4iICkgXSA8LSAieW91bmciCiAgICBmYWN0IDwtIGZhY3RvciggZmFjdCApCiAgICAKICAgICMgUHJlcGFyZSBtYXRyaXggZm9yIHQtdGVzdCBpbnB1dAogICAgVFBNX05TQ19tYXQgPC0gVFBNX05TQ19zdWJwb3AKICAgIFRQTV9OU0NfbWF0IDwtIGFzLm1hdHJpeCggVFBNX05TQ19tYXQgKSAKICAgIAogICAgIyBSdW4gdC10ZXN0IHdpdGggcm93dHRlc3RzIGZ1bmN0aW9uIGZyb20gZ2VuZWZpbHRlciBwYWNrYWdlcwogICAgdF90ZXN0X05TQ3NfU01BUlRzZXEyIDwtIHJvd3R0ZXN0cyh4ID0gVFBNX05TQ19tYXQgLCBmYWMgPSBmYWN0ICkKICAgIAogICAgIyBBZGQgZW5zZW1ibF9nZW5lX2lkIGFzIGNvbHVtbiBmcm9tIHRoZSByb3duYW1lcwogICAgdF90ZXN0X05TQ3NfU01BUlRzZXEyJGVuc2VtYmxfZ2VuZV9pZCA8LSByb3duYW1lcyh0X3Rlc3RfTlNDc19TTUFSVHNlcTIpIAogICAgCiAgICAjIEpvaW4gdGhlIHRhYmxlcwogICAgdGFibGVfc21zMl9tZXJnZWRfd2l0aF90dGVzdCA8LSBmdWxsX2pvaW4oeCA9IHRhYmxlX3NtczIgLCB5ID0gdF90ZXN0X05TQ3NfU01BUlRzZXEyICwgYnkgPSAiZW5zZW1ibF9nZW5lX2lkIiApCgogICAgdGFibGVfc21zMl9tZXJnZWRfd2l0aF90dGVzdAp9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBSdW4gdGhlIHQtdGVzdCBmb3IgYWxsIHN1YnBvcHVsYXRpb25zIGluZGl2aWR1YWxseQoKc3VicG9wdWxhdGlvbnMgPC0gbGlzdChxTlNDMSA9ICJxTlNDMSIsIHFOU0MyID0gInFOU0MyIiwgYU5TQzEgPSAiYU5TQzEiLCBhTlNDMiA9ICJhTlNDMiIpCgp0dGVzdF9yZXN1bHRzX2NvaGVuc2QgPC0gbGFwcGx5KFggPSBzdWJwb3B1bGF0aW9ucyAsIEZVTiA9IHJ1bl90dGVzdF9hbmRfY2FsY3VsYXRlX0NvaGVuc19kICkgCgojIE9yZGVyIHRoZSB0YWJsZSBieSBjb2hlbnMgZAp0dGVzdF9yZXN1bHRzX2NvaGVuc2QgPC0gbGFwcGx5KHR0ZXN0X3Jlc3VsdHNfY29oZW5zZCwgRlVOID0gZnVuY3Rpb24oeCl7YXJyYW5nZSh4LCBkZXNjKGRpZmZlcmVuY2Vfb2ZfYXZnL21lYW5fc2QpKX0gKQoKIyMgU2F2ZSB0aGUgcmVzdWx0cyBhcyBhIGNzdiBmaWxlCiMgd3JpdGUuY3N2KHggPSB0dGVzdF9yZXN1bHRzX2NvaGVuc2RbWzFdXSAsIGZpbGUgPSBwYXN0ZTAoIkRFX3Jlc3VsdHMvREVfTlNDX1NtYXJ0U2VxMi9zdWJwb3B1bGF0aW9ucy9ERV9TbWFydFNlcTJfdC10ZXN0X0NvaGVuc0RfIixzdWJwb3B1bGF0aW9uc1tbMV1dLCIuY3N2IikgKQoKIyB3cml0ZS5jc3YoeCA9IHR0ZXN0X3Jlc3VsdHNfY29oZW5zZFtbMl1dICwgZmlsZSA9IHBhc3RlMCgiREVfcmVzdWx0cy9ERV9OU0NfU21hcnRTZXEyL3N1YnBvcHVsYXRpb25zL0RFX1NtYXJ0U2VxMl90LXRlc3RfQ29oZW5zRF8iLHN1YnBvcHVsYXRpb25zW1syXV0sIi5jc3YiKSApCgojIHdyaXRlLmNzdih4ID0gdHRlc3RfcmVzdWx0c19jb2hlbnNkW1szXV0gLCBmaWxlID0gcGFzdGUwKCJERV9yZXN1bHRzL0RFX05TQ19TbWFydFNlcTIvc3VicG9wdWxhdGlvbnMvREVfU21hcnRTZXEyX3QtdGVzdF9Db2hlbnNEXyIsc3VicG9wdWxhdGlvbnNbWzNdXSwiLmNzdiIpICkKCiMgd3JpdGUuY3N2KHggPSB0dGVzdF9yZXN1bHRzX2NvaGVuc2RbWzRdXSAsIGZpbGUgPSBwYXN0ZTAoIkRFX3Jlc3VsdHMvREVfTlNDX1NtYXJ0U2VxMi9zdWJwb3B1bGF0aW9ucy9ERV9TbWFydFNlcTJfdC10ZXN0X0NvaGVuc0RfIixzdWJwb3B1bGF0aW9uc1tbNF1dLCIuY3N2IikgKQpgYGAKCiMjIyMgRGlmZmVyZW5jZSBvZiB0aGUgbWVhbiBFeHByZXNzaW9uIHZzLiBNZWFuIFNEIFBsb3RzCgojIyMjIyBxTlNDMSB2cy4gcU5TQzIgCgpgYGB7cn0KIyMgdC10ZXN0IGJldHdlZW4gcU5TQzEgYW5kIHFOU0MyIFNNQVJUc2VxMgojIyBTdWJzZXQgY2VsbHMgZm9yIGluZGl2aWR1YWwgc3VicG9wdWxhdGlvbnMKVFBNX05TQ19xTlNDMSA8LSBUUE1fTlNDWyxhcy5jaGFyYWN0ZXIoTlNDX2Fubm9bTlNDX2Fubm8kdHlwZSA9PSAicU5TQzEiLF0kY2VsbCldClRQTV9OU0NfcU5TQzIgPC0gVFBNX05TQ1ssYXMuY2hhcmFjdGVyKE5TQ19hbm5vW05TQ19hbm5vJHR5cGUgPT0gInFOU0MyIixdJGNlbGwpXQoKVFBNX05TQ19hTlNDMSA8LSBUUE1fTlNDWyxhcy5jaGFyYWN0ZXIoTlNDX2Fubm9bTlNDX2Fubm8kdHlwZSA9PSAiYU5TQzEiLF0kY2VsbCldClRQTV9OU0NfYU5TQzIgPC0gVFBNX05TQ1ssYXMuY2hhcmFjdGVyKE5TQ19hbm5vW05TQ19hbm5vJHR5cGUgPT0gImFOU0MyIixdJGNlbGwpXQoKClRQTV9OU0NfcU5TQzFfcU5TQzIgPC0gYXMubWF0cml4KCBjYmluZCggVFBNX05TQ19xTlNDMSAsIFRQTV9OU0NfcU5TQzIgKSApIAoKcTFxMiA8LSBjKCByZXAoICJxTlNDMSIgLCAxMzQgKSAsIHJlcCggInFOU0MyIiAsIDQwICkgKQp0X3Rlc3RfcU5TQzFfdnNfMl9TTUFSVHNlcTIgPC0gcm93dHRlc3RzKHggPSBhcy5tYXRyaXgoIFRQTV9OU0NfcU5TQzFfcU5TQzIgKSAsIGZhYyA9IGZhY3RvciggcTFxMiApICkKCnRhYiA8LSBkYXRhLmZyYW1lKAogIGVuc2VtYmxfZ2VuZV9pZCA9IHJvd25hbWVzKFRQTV9OU0NfcU5TQzEpLAogIG1lYW5fcU5TQzEgPSByb3dNZWFucyggVFBNX05TQ19xTlNDMSApICwKICBtZWFuX3FOU0MyID0gcm93TWVhbnMoIFRQTV9OU0NfcU5TQzIgKSAsIAogIHZhcl9xTlNDMSA9IGFwcGx5KFggPSBUUE1fTlNDX3FOU0MxICwgTUFSR0lOID0gMSAsIEZVTiA9IHZhciApLAogIHZhcl9xTlNDMiA9IGFwcGx5KFggPSBUUE1fTlNDX3FOU0MyICwgTUFSR0lOID0gMSAsIEZVTiA9IHZhciApLAogIHNkX3FOU0MxID0gYXBwbHkoWCA9IFRQTV9OU0NfcU5TQzEgLCBNQVJHSU4gPSAxICwgRlVOID0gc2QgKSwKICBzZF9xTlNDMiA9IGFwcGx5KFggPSBUUE1fTlNDX3FOU0MyICwgTUFSR0lOID0gMSAsIEZVTiA9IHNkICkKKQoKdGFiJG1lYW5fdmFyIDwtIGFwcGx5KFggPSB0YWJbLGMoInZhcl9xTlNDMSIsInZhcl9xTlNDMiIpXSAsIE1BUkdJTiA9IDEgLCBGVU4gPSBtZWFuICkKdGFiJG1lYW5fc2QgPC0gYXBwbHkoWCA9IHRhYlssYygic2RfcU5TQzEiLCJzZF9xTlNDMiIpXSAsIE1BUkdJTiA9IDEgLCBGVU4gPSBtZWFuICkKdGFiJGRpZmZlcmVuY2Vfb2ZfYXZnIDwtICh0YWIkbWVhbl9xTlNDMSAtIHRhYiRtZWFuX3FOU0MyICkKdGFiJCdkaWZmZXJlbmNlX29mX2F2Zy9tZWFuX3NkJyA8LSB0YWIkZGlmZmVyZW5jZV9vZl9hdmcvdGFiJG1lYW5fc2QKCiMgQWRkIGVuc2VtYmxfZ2VuZV9pZCBhcyBjb2x1bW4gZnJvbSB0aGUgcm93bmFtZXMKdF90ZXN0X3FOU0MxX3ZzXzJfU01BUlRzZXEyJGVuc2VtYmxfZ2VuZV9pZCA8LSByb3duYW1lcyh0X3Rlc3RfcU5TQzFfdnNfMl9TTUFSVHNlcTIpIAoKIyBKb2luIHRoZSB0YWJsZXMKdF90ZXN0X3FOU0MxX3ZzXzJfU01BUlRzZXEyX21lcmdlZF93aXRoX3R0ZXN0IDwtIGZ1bGxfam9pbih4ID0gdGFiICwgeSA9IHRfdGVzdF9xTlNDMV92c18yX1NNQVJUc2VxMiAsIGJ5ID0gImVuc2VtYmxfZ2VuZV9pZCIgKQoKCmxpYnJhcnkoY293cGxvdCkKCmdncGxvdChkYXRhID0gdF90ZXN0X3FOU0MxX3ZzXzJfU01BUlRzZXEyX21lcmdlZF93aXRoX3R0ZXN0ICwgYWVzKHkgPSBtZWFuX3NkICwgeCA9IG1lYW5fcU5TQzEgLSBtZWFuX3FOU0MyICwgY29sb3IgPSBhYnMoZGlmZmVyZW5jZV9vZl9hdmcvbWVhbl9zZCkgPiAwLjggKSkgKyBnZW9tX3BvaW50KCBhbHBoYSA9IDAuNSAsIHNpemUgPSAxICAgICkgKyBnZ3RpdGxlKCJDb21wYXJpc29uOiBxTlNDMSB2cyBxTlNDMiIpICsgeGxpbShjKC01LDUpKSArIHRoZW1lX2Nvd3Bsb3QoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXk4MCIpKSArIHhsYWIoIkRpZmZlcmVuY2Ugb2YgbWVhbiBleHByZXNzaW9ucyIpICsgeWxhYigiQXZlcmFnZSBTRCIpCgpnZ3Bsb3QoZGF0YSA9IHRhYiAsIGFlcyh5ID0gbWVhbl9zZCAsIHggPSBtZWFuX3FOU0MxIC0gbWVhbl9xTlNDMiApKSArIGdlb21fcG9pbnQoIGFscGhhID0gMC4xICwgc2l6ZSA9IDEgKSArIGdndGl0bGUoIkNvbXBhcmlzb246IHFOU0MxIHZzIHFOU0MyIikgKyB4bGltKGMoLTUsNSkpICsgdGhlbWVfY293cGxvdCgpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleTgwIikpICsgeGxhYigiRGlmZmVyZW5jZSBvZiBtZWFuIGV4cHJlc3Npb25zIikgKyB5bGFiKCJBdmVyYWdlIFNEIikKCmBgYAoKIyMjIyMgcU5TQzE6IG9sZCB2cy4geW91bmcKCmBgYHtyfQp0YWJfcTFfb2xkX3lvdW5nIDwtIHJ1bl90dGVzdF9hbmRfY2FsY3VsYXRlX0NvaGVuc19kKHN1YnBvcCA9ICJxTlNDMSIgKQoKZ2dwbG90KGRhdGEgPSB0YWJfcTFfb2xkX3lvdW5nICwgYWVzKHkgPSBtZWFuX3NkICwgeCA9IGRpZmZlcmVuY2Vfb2ZfYXZnICwgY29sb3IgPSBhYnMoZGlmZmVyZW5jZV9vZl9hdmcvbWVhbl9zZCkgPiAwLjggICkpICsgZ2VvbV9wb2ludCggYWxwaGEgPSAwLjUgLCBzaXplID0gMSApICsgZ2d0aXRsZSgiQ29tcGFyaXNvbjogcU5TQzEgLSBvbGQgdnMgeW91bmciKSArIHhsaW0oYygtNSw1KSkgKyB0aGVtZV9jb3dwbG90KCkgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5ODAiKSkgICsgeGxhYigiRGlmZmVyZW5jZSBvZiBtZWFuIGV4cHJlc3Npb25zIikgKyB5bGFiKCJBdmVyYWdlIFNEIikgCgpnZ3Bsb3QoZGF0YSA9IHRhYl9xMV9vbGRfeW91bmcgLCBhZXMoeSA9IG1lYW5fc2QgLCB4ID0gZGlmZmVyZW5jZV9vZl9hdmcgKSkgKyBnZW9tX3BvaW50KCBhbHBoYSA9IDAuMSAsIHNpemUgPSAxICkgKyBnZ3RpdGxlKCJDb21wYXJpc29uOiBxTlNDMSAtIG9sZCB2cyB5b3VuZyIpICsgeGxpbShjKC01LDUpKSArIHRoZW1lX2Nvd3Bsb3QoKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXk4MCIpKSAgKyB4bGFiKCJEaWZmZXJlbmNlIG9mIG1lYW4gZXhwcmVzc2lvbnMiKSArIHlsYWIoIkF2ZXJhZ2UgU0QiKSAKYGBgCgojIEV1Y2xpZGVhbiBEaXN0YW5jZXMgKHdvcmsgb24gaXQpCgojIyBMb2FkIHRoZSBUUE0gdmFsdWVzCgpgYGB7cn0Kc21hcnRzZXEyX2RhdGEgPC0gcmVhZC5jc3YoZmlsZSA9ICJjb3VudF90YWJsZS9UUE1fTlNDX2FuZF9Bc3Ryby9vbGRfeW91bmdfY29tYmluZWQvR2VuZV9leHByZXNzaW9uX21hdHJpeF9UUE1fYWxsLmNzdiIgLCByb3cubmFtZXMgPSAxKQoKc21hcnRzZXEyX2RhdGEgPC0gc21hcnRzZXEyX2RhdGEgJT4lIHJlbW92ZV9yb3duYW1lcygpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoImdlbmVfaWQiKQpgYGAKCkFsc28gd2UgbG9hZCB0aGUgYW5ub3RhdGlvbgoKYGBge3J9CnNtYXJ0c2VxMl9hbm5vdGF0aW9uIDwtIHJlYWQuY3N2KGZpbGUgPSAiY291bnRfdGFibGUvY2VsbF9hbm5vdGF0aW9uX05TQ19Bc3Ryby9vbGRfeW91bmdfY29tYmluZWQvY2VsbF9hbm5vdGF0aW9uLmNzdiIgLCByb3cubmFtZXMgPSAxKQpgYGAKCldoaWNoIGNlbGx0eXBlcyBkbyB3ZSBoYXZlPwoKYGBge3J9CmNlbGx0eXBlcyA8LSB1bmlxdWUoYXMuY2hhcmFjdGVyKHNtYXJ0c2VxMl9hbm5vdGF0aW9uJHR5cGUpKQoKY2VsbHR5cGVzCmBgYAoKIyMgQ3JlYXRlIFNldXJhdCBvYmplY3QKYGBge3J9CnNldXJhdF9zbXMyIDwtIENyZWF0ZVNldXJhdE9iamVjdChyYXcuZGF0YSA9IHNtYXJ0c2VxMl9kYXRhICwgbWluLmNlbGxzID0gMywgcHJvamVjdCA9ICJ5b3VuZ192c19vbGRfU21hcnRTZXEyIikKCnNldXJhdF9zbXMyIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IHNldXJhdF9zbXMyLCBtZXRhZGF0YSA9IHNtYXJ0c2VxMl9hbm5vdGF0aW9uICU+JSByZW1vdmVfcm93bmFtZXMoKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJjZWxsIikgKQoKc2V1cmF0X3NtczIgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSBzZXVyYXRfc21zMiwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiApCgpzZXVyYXRfc21zMiA8LSBTY2FsZURhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIsIHZhcnMudG8ucmVncmVzcyA9IGMoIm5VTUkiLCAibkdlbmUiKSkKCnNldXJhdF9zbXMyIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IHNldXJhdF9zbXMyLCBtZWFuLmZ1bmN0aW9uID0gRXhwTWVhbiwgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwgeS5jdXRvZmYgPSAwLjc1KQpgYGAKCmBgYHtyfQpnZW5lcy52YXIgPC0gYXBwbHkoWCA9IHNldXJhdF9zbXMyQHJhdy5kYXRhICwgTUFSR0lOID0gMSAsIEZVTiA9IHZhcikKZ2VuZXMudmFyLnRvcCA8LSBuYW1lcyggc29ydChnZW5lcy52YXIgLCBkZWNyZWFzaW5nID0gVFJVRSlbMToyMDAwXSApCgpzZXVyYXRfc21zMkB2YXIuZ2VuZXMgPC0gZ2VuZXMudmFyLnRvcApgYGAKCmBgYHtyfQpzZXVyYXRfc21zMkBpbXB1dGVkIDwtIGFzLmRhdGEuZnJhbWUubWF0cml4KHNldXJhdF9zbXMyQGRhdGEpCmBgYAoKCmBgYHtyfQpzZXVyYXRfc21zMiA8LSBSdW5QQ0Eob2JqZWN0ID0gc2V1cmF0X3NtczIsIHBjLmdlbmVzID0gc2V1cmF0X3NtczJAdmFyLmdlbmVzLCBkby5wcmludCA9IFRSVUUsIHBjcy5wcmludCA9IDE6NSwgZ2VuZXMucHJpbnQgPSA1ICwgdXNlLmltcHV0ZWQgPSBUUlVFICkKc2V1cmF0X3NtczIgPC0gUHJvamVjdFBDQShvYmplY3QgPSBzZXVyYXRfc21zMiApCnNldXJhdF9zbXMyIDwtIEphY2tTdHJhdyhvYmplY3QgPSBzZXVyYXRfc21zMiAgKQpgYGAKCmBgYHtyfQpQQ0VsYm93UGxvdChvYmplY3QgPSBzZXVyYXRfc21zMikKYGBgCgpgYGB7cn0Kc2V1cmF0X3NtczIgPC0gU2V0QWxsSWRlbnQob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBpZCA9ICJ0eXBlIikKYGBgCgoKYGBge3J9ClBDQVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBkaW0uMSA9IDEsIGRpbS4yID0gMikKYGBgCgpgYGB7cn0KUENBUGxvdChvYmplY3QgPSBzZXVyYXRfc21zMiAsIGRpbS4xID0gMSwgZGltLjIgPSAzKQpgYGAKCmBgYHtyfQpQQ0FQbG90KG9iamVjdCA9IHNldXJhdF9zbXMyICwgZGltLjEgPSAyLCBkaW0uMiA9IDMpCmBgYAoKYGBge3J9ClBDQVBsb3Qob2JqZWN0ID0gc2V1cmF0X3NtczIgLCBkaW0uMSA9IDEsIGRpbS4yID0gNCkKYGBgCgpgYGB7cn0KUENBUGxvdChvYmplY3QgPSBTZXRBbGxJZGVudCggc2V1cmF0X3NtczIgLCBpZCA9ICJhZ2UiICkgLCBkaW0uMSA9IDEsIGRpbS4yID0gNCkKYGBgCgoKTG9nIHRyYW5zZm9ybSB0aGUgVFBNIHZhbHVlcwoKYGBge3J9CnNtYXJ0c2VxMl9kYXRhIDwtIGxvZygxK3NtYXJ0c2VxMl9kYXRhKQpgYGAKCgpNYWtlIGEgbWF0cml4IG9mIHRoZSBkYXRhCgpgYGB7cn0KZGF0YV9tYXRyaXhfY2VsbHR5cGVzIDwtIGxhcHBseSggWCA9IGNlbGx0eXBlcywgRlVOID0gZnVuY3Rpb24oeCl7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxzIDwtIGZpbHRlcihzbWFydHNlcTJfYW5ub3RhdGlvbiAsIHR5cGUgPT0geCkgJT4lIHB1bGwoY2VsbCkgJT4lIGFzLmNoYXJhY3RlcigpCiAgICAgICAgICAgICAgICAgICAgICAgICMgdChhcy5tYXRyaXgoc21hcnRzZXEyX2RhdGFbLGNlbGxzXSkpCiAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICBGZXRjaERhdGEob2JqZWN0ID0gc2V1cmF0X3NtczIgLCB2YXJzLmFsbCA9IGMoIlBDMSIsIlBDMiIsIlBDMyIsIlBDNCIsIlBDNSIpICwgY2VsbHMudXNlID0gY2VsbHMgKQogICAgICAgICAgICAgICAgICAgICAgfSkKYGBgCgpOb3cgd2UgY2FsY3VsYXRlIHRoZSBldWNsaWRlYW4gZGlzdGFuY2UgYmV0d2VlbiBhbGwgdGhlIGNlbGxzIGZyb20gb25lIGNlbGx0eXBlCgpgYGB7cn0KZXVjX2Rpc3RfY2VsbHR5cGVzIDwtIGxhcHBseSggZGF0YV9tYXRyaXhfY2VsbHR5cGVzICwgRlVOID0gZnVuY3Rpb24oeCl7YXMubWF0cml4KGRpc3QoeCA9IHgsIG1ldGhvZCA9ICJldWNsaWRlYW4iICwgdXBwZXIgPSBUUlVFKSl9ICkKYGBgCgpgYGB7ciBmaWcuYXNwPTAuOX0KcGhlYXRtYXAoCiAgbWFpbiA9IGNlbGx0eXBlc1tbMV1dLAogIG1hdCA9IGV1Y19kaXN0X2NlbGx0eXBlc1tbMV1dLAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCAKICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgc2hvd19yb3duYW1lcyA9IFRSVUUgLCAKICBzaG93X2NvbG5hbWVzID0gVFJVRSAsIAogIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFICwgCiAgbnVtYmVyX2NvbG9yID0gImJsYWNrIiAsIAogIGZvbnRzaXplID0gMTQKKQpgYGAKCmBgYHtyIGZpZy5hc3A9MC45fQpwaGVhdG1hcCgKICBtYWluID0gY2VsbHR5cGVzW1syXV0sCiAgbWF0ID0gZXVjX2Rpc3RfY2VsbHR5cGVzW1syXV0sCiAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsIAogIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAKICBzaG93X3Jvd25hbWVzID0gVFJVRSAsIAogIHNob3dfY29sbmFtZXMgPSBUUlVFICwgCiAgZGlzcGxheV9udW1iZXJzID0gRkFMU0UgLCAKICBudW1iZXJfY29sb3IgPSAiYmxhY2siICwgCiAgZm9udHNpemUgPSAxNAopCmBgYAoKYGBge3IgZmlnLmFzcD0wLjl9CnBoZWF0bWFwKAogIG1haW4gPSBjZWxsdHlwZXNbWzNdXSwKICBtYXQgPSBldWNfZGlzdF9jZWxsdHlwZXNbWzNdXSwKICBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsIAogIHNob3dfcm93bmFtZXMgPSBUUlVFICwgCiAgc2hvd19jb2xuYW1lcyA9IFRSVUUgLCAKICBkaXNwbGF5X251bWJlcnMgPSBGQUxTRSAsIAogIG51bWJlcl9jb2xvciA9ICJibGFjayIgLCAKICBmb250c2l6ZSA9IDE0CikKYGBgCgpgYGB7ciBmaWcuYXNwPTAuOSwgZmlnLndpZHRoPTMwfQpwaGVhdG1hcCgKICBtYWluID0gY2VsbHR5cGVzW1s0XV0sCiAgbWF0ID0gZXVjX2Rpc3RfY2VsbHR5cGVzW1s0XV0sCiAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsIAogIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAKICBzaG93X3Jvd25hbWVzID0gVFJVRSAsIAogIHNob3dfY29sbmFtZXMgPSBUUlVFICwgCiAgZGlzcGxheV9udW1iZXJzID0gRkFMU0UgLCAKICBudW1iZXJfY29sb3IgPSAiYmxhY2siICwgCiAgZm9udHNpemUgPSAxNAopCmBgYAoKYGBge3IgZmlnLmFzcD0wLjksIGZpZy53aWR0aD0xMH0KcGhlYXRtYXAoCiAgbWFpbiA9IGNlbGx0eXBlc1tbNV1dLAogIG1hdCA9IGV1Y19kaXN0X2NlbGx0eXBlc1tbNV1dLAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCAKICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgc2hvd19yb3duYW1lcyA9IFRSVUUgLCAKICBzaG93X2NvbG5hbWVzID0gVFJVRSAsIAogIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFICwgCiAgbnVtYmVyX2NvbG9yID0gImJsYWNrIiAsIAogIGZvbnRzaXplID0gMTQKKQpgYGAKCiMjIENvbXBhcmUgYWxsIHNhbXBsZXMgdG8gZWFjaCBvdGhlcgoKYGBge3J9CnJvd25hbWVzKHNtYXJ0c2VxMl9hbm5vdGF0aW9uKSA8LSBOVUxMCgphbm5vIDwtIHNtYXJ0c2VxMl9hbm5vdGF0aW9uICU+JSBtdXRhdGUodHlwZSA9IGZhY3Rvcih0eXBlICwgbGV2ZWxzID0gYygicU5TQzEiLCJxTlNDMiIsImFOU0MxIiwiYU5TQzIiLCJBc3RybyIpKSkgJT4lIGFycmFuZ2UoYWdlICwgdHlwZSkgJT4lIGNvbHVtbl90b19yb3duYW1lcyggdmFyID0gImNlbGwiKQpgYGAKCmBgYHtyfQpkaXN0X2FsbF9zYW1wbGVzIDwtIGFzLm1hdHJpeChkaXN0KHggPSB0KGFzLm1hdHJpeChzbWFydHNlcTJfZGF0YSlbLHJvd25hbWVzKGFubm8pXSksIG1ldGhvZCA9ICJldWNsaWRlYW4iICwgdXBwZXIgPSBUUlVFKSkKYGBgCgpgYGB7ciBmaWcuYXNwPTAuOSAsIGZpZy53aWR0aD0yMH0KcGhlYXRtYXAoCiAgbWFpbiA9ICJFdWNsaWRlYW4gRGlzdGFuY2UgYmV0d2VlbiBhbGwgc2FtcGxlcyIsCiAgbWF0ID0gZGlzdF9hbGxfc2FtcGxlcywKICBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsCiAgYW5ub3RhdGlvbl9yb3cgPSBhbm5vLAogIGFubm90YXRpb25fY29sID0gYW5ubywKICBhbm5vdGF0aW9uX2NvbG9ycyA9IGxpc3QoIHR5cGUgPSBjKCBxTlNDMSA9ICJzdGVlbGJsdWUiICwgcU5TQzIgPSAic3RlZWxibHVlMSIgLCBhTlNDMSA9ICJ0b21hdG8iICwgYU5TQzIgPSAic2llbm5hMSIsIEFzdHJvID0gImdyZXkiKSAsIGFnZSA9IGMoeW91bmcgPSAiZm9yZXN0Z3JlZW4iICwgb2xkID0gInJlZCIpKSAsCiAgc2hvd19yb3duYW1lcyA9IFRSVUUgLCAKICBzaG93X2NvbG5hbWVzID0gVFJVRSAsIAogIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFICwgCiAgbnVtYmVyX2NvbG9yID0gImJsYWNrIiAsIAogIGZvbnRzaXplID0gMTQKKQpgYGAKCiMjIERlbnNpdHkgb2YgZXVjbGlkZWFuIGRpc3RhbmNlcwoKYGBge3J9CmRmLnBsb3QubGlzdCA8LSBsYXBwbHkoIFggPSBldWNfZGlzdF9jZWxsdHlwZXMsIEZVTiA9IGZ1bmN0aW9uKHgpewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJjZWxsMSIpICU+JSBnYXRoZXIoa2V5ID0gImNlbGwyIiAsIHZhbHVlID0gImV1Y2xpZGVhbl9kaXN0YW5jZSIgLCAtY2VsbDEpICU+JSBsZWZ0X2pvaW4oIHkgPSBkcGx5cjo6cmVuYW1lKGFubm8sIGFnZV9jZWxsMSA9IGFnZSkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbiggdmFyID0gImNlbGwxIikgLCBieSA9ICJjZWxsMSIgKSAlPiUgbGVmdF9qb2luKCB5ID0gZHBseXI6OnJlbmFtZShhbm5vLCBhZ2VfY2VsbDIgPSBhZ2UpICU+JSByb3duYW1lc190b19jb2x1bW4oIHZhciA9ICJjZWxsMiIpICwgYnkgPSAiY2VsbDIiICkgJT4lIG11dGF0ZShjb21wYXJpc29uID0gcGFzdGUoYWdlX2NlbGwxICwgYWdlX2NlbGwyICwgc2VwID0gIl8iKSkgJT4lIGRwbHlyOjpmaWx0ZXIoY29tcGFyaXNvbiAlaW4lIGMoIm9sZF9vbGQiLCJ5b3VuZ19vbGQiLCJ5b3VuZ195b3VuZyIpKQp9KQpgYGAKCmBgYHtyfQpnZy5saXN0IDwtIGxhcHBseSggWCA9IGRmLnBsb3QubGlzdCwgRlVOID0gZnVuY3Rpb24oeCl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KGRhdGEgPSB4LCBtYXBwaW5nID0gYWVzKHggPSBldWNsaWRlYW5fZGlzdGFuY2UgLCBjb2xvciA9IGNvbXBhcmlzb24gLCBmaWxsID0gY29tcGFyaXNvbiApKSArIGdlb21fZGVuc2l0eSggYWxwaGEgPSAwLjMpICsgZ2d0aXRsZSggcGFzdGUwKHVuaXF1ZShhcy5jaGFyYWN0ZXIoeCR0eXBlLngpKSkgKQp9KQpgYGAKCiMjIyBBc3RybwoKYGBge3IgZmlnLndpZHRoPTUsZmlnLmhlaWdodD0yfQpwcmludChnZy5saXN0W1sxXV0pCmBgYAoKIyMjIGFOU0MxCgpgYGB7ciBmaWcud2lkdGg9NSxmaWcuaGVpZ2h0PTJ9CnByaW50KGdnLmxpc3RbWzJdXSkKYGBgCgojIyMgYU5TQzIKCmBgYHtyIGZpZy53aWR0aD01LGZpZy5oZWlnaHQ9Mn0KcHJpbnQoZ2cubGlzdFtbM11dKQpgYGAKCiMjIyBxTlNDMQoKYGBge3IgZmlnLndpZHRoPTUsZmlnLmhlaWdodD0yfQpwcmludChnZy5saXN0W1s0XV0pCmBgYAoKIyMjIHFOU0MyCgpgYGB7ciBmaWcud2lkdGg9NSxmaWcuaGVpZ2h0PTJ9CnByaW50KGdnLmxpc3RbWzVdXSkKYGBgCgoKIyMgRXVjbGlkZWFuIERpc3RhbmNlcyBiZXR3ZWVuIGNlbGx0eXBlcwoKYGBge3J9CmNlbGx0eXBlX2NvbXBhcmlzb25zIDwtIGxpc3QoQXN0cm9fcU5TQzEgPSBjKCJBc3RybyIsInFOU0MxIikgLCBxTlNDMV9xTlNDMiA9IGMoInFOU0MxIiwicU5TQzIiKSAsIHFOU0MyX2FOU0MxID0gYygicU5TQzIiLCJhTlNDMSIpICwgYU5TQzFfYU5TQzIgPSBjKCJhTlNDMSIsImFOU0MyIikgLCBxTlNDMV9hTlNDMiA9IGMoInFOU0MxIiwiYU5TQzIiKSAgKQoKY2VsbHR5cGVfY29tcGFyaXNvbnMKYGBgCgpNYWtlIGEgbWF0cml4IG9mIHRoZSBkYXRhCgpgYGB7cn0KZGF0YV9tYXRyaXhfbGluZWFnZSA8LSBsYXBwbHkoIFggPSBjZWxsdHlwZV9jb21wYXJpc29ucywgRlVOID0gZnVuY3Rpb24oeCl7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxzIDwtIGZpbHRlcihzbWFydHNlcTJfYW5ub3RhdGlvbiAsIHR5cGUgJWluJSB4KSAlPiUgcHVsbChjZWxsKSAlPiUgYXMuY2hhcmFjdGVyKCkKICAgICAgICAgICAgICAgICAgICAgICAgIyB0KGFzLm1hdHJpeChzbWFydHNlcTJfZGF0YVssY2VsbHNdKSkKICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgIEZldGNoRGF0YShvYmplY3QgPSBzZXVyYXRfc21zMiAsIHZhcnMuYWxsID0gYygiUEMxIiwiUEMyIiwiUEMzIiwiUEM0IiwiUEM1IikgLCBjZWxscy51c2UgPSBjZWxscyApCiAgICAgICAgICAgICAgICAgICAgICB9KQpgYGAKCk5vdyB3ZSBjYWxjdWxhdGUgdGhlIGV1Y2xpZGVhbiBkaXN0YW5jZSBiZXR3ZWVuIGFsbCB0aGUgY2VsbHMgZnJvbSB0aGUgY29tcGFyaXNvbgoKYGBge3J9CmV1Y19kaXN0X2xpbmVhZ2VfYWxsIDwtIGxhcHBseSggZGF0YV9tYXRyaXhfbGluZWFnZSAsIEZVTiA9IGZ1bmN0aW9uKHgpe2FzLm1hdHJpeChkaXN0KHggPSB4LCBtZXRob2QgPSAiZXVjbGlkZWFuIiAsIHVwcGVyID0gVFJVRSkpfSApCmBgYAoKYGBge3IgZmlnLmFzcD0wLjksIGZpZy53aWR0aD0xMH0KcGhlYXRtYXAoCiAgbWFpbiA9IHBhc3RlKGNlbGx0eXBlX2NvbXBhcmlzb25zW1sxXV0sIGNvbGxhcHNlID0gIl92c18iKSwKICBtYXQgPSBldWNfZGlzdF9saW5lYWdlX2FsbFtbMV1dLAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCAKICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgc2hvd19yb3duYW1lcyA9IFRSVUUgLCAKICBzaG93X2NvbG5hbWVzID0gVFJVRSAsIAogIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFICwgCiAgbnVtYmVyX2NvbG9yID0gImJsYWNrIiAsIAogIGZvbnRzaXplID0gMTQKKQpgYGAKCmBgYHtyIGZpZy5hc3A9MC45LCBmaWcud2lkdGg9MTB9CnBoZWF0bWFwKAogIG1haW4gPSBwYXN0ZShjZWxsdHlwZV9jb21wYXJpc29uc1tbMl1dLCBjb2xsYXBzZSA9ICJfdnNfIiksCiAgbWF0ID0gZXVjX2Rpc3RfbGluZWFnZV9hbGxbWzJdXSwKICBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsIAogIHNob3dfcm93bmFtZXMgPSBUUlVFICwgCiAgc2hvd19jb2xuYW1lcyA9IFRSVUUgLCAKICBkaXNwbGF5X251bWJlcnMgPSBGQUxTRSAsIAogIG51bWJlcl9jb2xvciA9ICJibGFjayIgLCAKICBmb250c2l6ZSA9IDE0CikKYGBgCgpgYGB7ciBmaWcuYXNwPTAuOSwgZmlnLndpZHRoPTEwfQpwaGVhdG1hcCgKICBtYWluID0gcGFzdGUoY2VsbHR5cGVfY29tcGFyaXNvbnNbWzNdXSwgY29sbGFwc2UgPSAiX3ZzXyIpLAogIG1hdCA9IGV1Y19kaXN0X2xpbmVhZ2VfYWxsW1szXV0sCiAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsIAogIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAKICBzaG93X3Jvd25hbWVzID0gVFJVRSAsIAogIHNob3dfY29sbmFtZXMgPSBUUlVFICwgCiAgZGlzcGxheV9udW1iZXJzID0gRkFMU0UgLCAKICBudW1iZXJfY29sb3IgPSAiYmxhY2siICwgCiAgZm9udHNpemUgPSAxNAopCmBgYAoKYGBge3IgZmlnLmFzcD0wLjksIGZpZy53aWR0aD0xMH0KcGhlYXRtYXAoCiAgbWFpbiA9IHBhc3RlKGNlbGx0eXBlX2NvbXBhcmlzb25zW1s0XV0sIGNvbGxhcHNlID0gIl92c18iKSwKICBtYXQgPSBldWNfZGlzdF9saW5lYWdlX2FsbFtbNF1dLAogIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCAKICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgc2hvd19yb3duYW1lcyA9IFRSVUUgLCAKICBzaG93X2NvbG5hbWVzID0gVFJVRSAsIAogIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFICwgCiAgbnVtYmVyX2NvbG9yID0gImJsYWNrIiAsIAogIGZvbnRzaXplID0gMTQKKQpgYGAKCmBgYHtyIGZpZy5hc3A9MC45LCBmaWcud2lkdGg9MTB9CnBoZWF0bWFwKAogIG1haW4gPSBwYXN0ZShjZWxsdHlwZV9jb21wYXJpc29uc1tbNV1dLCBjb2xsYXBzZSA9ICJfdnNfIiksCiAgbWF0ID0gZXVjX2Rpc3RfbGluZWFnZV9hbGxbWzVdXSwKICBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgCiAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsIAogIHNob3dfcm93bmFtZXMgPSBUUlVFICwgCiAgc2hvd19jb2xuYW1lcyA9IFRSVUUgLCAKICBkaXNwbGF5X251bWJlcnMgPSBGQUxTRSAsIAogIG51bWJlcl9jb2xvciA9ICJibGFjayIgLCAKICBmb250c2l6ZSA9IDE0CikKYGBgCgojIyMgRGVuc2l0eSBvZiBldWNsaWRlYW4gZGlzdGFuY2VzCgpgYGB7cn0KZGYucGxvdC5saXN0X2FsbCA8LSBsYXBwbHkoIFggPSBldWNfZGlzdF9saW5lYWdlX2FsbCwgRlVOID0gZnVuY3Rpb24oeCl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oImNlbGwxIikgJT4lIGdhdGhlcihrZXkgPSAiY2VsbDIiICwgdmFsdWUgPSAiZXVjbGlkZWFuX2Rpc3RhbmNlIiAsIC1jZWxsMSkgJT4lIGxlZnRfam9pbiggeSA9IGRwbHlyOjpyZW5hbWUoYW5ubywgdHlwZV9jZWxsMSA9IHR5cGUpICU+JSByb3duYW1lc190b19jb2x1bW4oIHZhciA9ICJjZWxsMSIpICwgYnkgPSAiY2VsbDEiICkgJT4lIGxlZnRfam9pbiggeSA9IGRwbHlyOjpyZW5hbWUoYW5ubywgdHlwZV9jZWxsMiA9IHR5cGUpICU+JSByb3duYW1lc190b19jb2x1bW4oIHZhciA9ICJjZWxsMiIpICwgYnkgPSAiY2VsbDIiICkgJT4lIG11dGF0ZShjb21wYXJpc29uID0gcGFzdGUodHlwZV9jZWxsMSAsIHR5cGVfY2VsbDIgLCBzZXAgPSAiXyIpKQp9KQpgYGAKCmBgYHtyfQpnZy5saXN0X2FsbCA8LSBsYXBwbHkoIFggPSBkZi5wbG90Lmxpc3RfYWxsLCBGVU4gPSBmdW5jdGlvbih4KXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoZGF0YSA9IHgsIG1hcHBpbmcgPSBhZXMoeCA9IGV1Y2xpZGVhbl9kaXN0YW5jZSAsIGNvbG9yID0gY29tcGFyaXNvbikpICsgZ2VvbV9kZW5zaXR5KCkgKyBnZ3RpdGxlKCAiIiApCn0pCmBgYAoKYGBge3J9CnByaW50KGdnLmxpc3RfYWxsW1sxXV0pCmBgYAoKYGBge3J9CnByaW50KGdnLmxpc3RfYWxsW1syXV0pCmBgYAoKYGBge3J9CnByaW50KGdnLmxpc3RfYWxsW1szXV0pCmBgYAoKYGBge3J9CnByaW50KGdnLmxpc3RfYWxsW1s0XV0pCmBgYAoKYGBge3J9CnByaW50KGdnLmxpc3RfYWxsW1s1XV0pCmBgYAoKCiMjIEV1Y2xpZGVhbiBkaXN0YW5jZXMgeW91bmcgdnMgb2xkCgpgYGB7cn0KcTFfcTJfZXVjX2Rpc3QgPC0gZGYucGxvdC5saXN0X2FsbCRxTlNDMV9xTlNDMiAlPiUgZmlsdGVyKGNvbXBhcmlzb24gPT0gInFOU0MxX3FOU0MyIikKYGBgCgoKYGBge3J9CmRmLnBsb3QubGlzdF9yZWYgPC0gbGFwcGx5KCBYID0gZXVjX2Rpc3RfY2VsbHR5cGVzLCBGVU4gPSBmdW5jdGlvbih4KXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ICAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSByb3duYW1lc190b19jb2x1bW4oImNlbGwxIikgJT4lIGdhdGhlcihrZXkgPSAiY2VsbDIiICwgdmFsdWUgPSAiZXVjbGlkZWFuX2Rpc3RhbmNlIiAsIC1jZWxsMSkgJT4lIGxlZnRfam9pbiggeSA9IGRwbHlyOjpyZW5hbWUoYW5ubywgYWdlX2NlbGwxID0gYWdlKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCB2YXIgPSAiY2VsbDEiKSAsIGJ5ID0gImNlbGwxIiApICU+JSBsZWZ0X2pvaW4oIHkgPSBkcGx5cjo6cmVuYW1lKGFubm8sIGFnZV9jZWxsMiA9IGFnZSkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbiggdmFyID0gImNlbGwyIikgLCBieSA9ICJjZWxsMiIgKSAlPiUgbXV0YXRlKGNvbXBhcmlzb24gPSBwYXN0ZShhZ2VfY2VsbDEgLCBhZ2VfY2VsbDIgLCBzZXAgPSAiXyIpKSAlPiUgZHBseXI6Om11dGF0ZSh0eXBlID0gYXMuY2hhcmFjdGVyKHR5cGUueCkgKSAlPiUgZHBseXI6OnNlbGVjdCggY2VsbDEsY2VsbDIsZXVjbGlkZWFuX2Rpc3RhbmNlLGNvbXBhcmlzb24gLCB0eXBlKSAlPiUgYmluZF9yb3dzKHExX3EyX2V1Y19kaXN0ICU+JSBkcGx5cjo6bXV0YXRlKHR5cGUgPSBhcy5jaGFyYWN0ZXIodHlwZV9jZWxsMSkgKSAlPiUgZHBseXI6OnNlbGVjdCggY2VsbDEsY2VsbDIsZXVjbGlkZWFuX2Rpc3RhbmNlLGNvbXBhcmlzb24sdHlwZSkpICU+JSBkcGx5cjo6ZmlsdGVyKGNvbXBhcmlzb24gJWluJSBjKCJvbGRfb2xkIiwieW91bmdfb2xkIiwieW91bmdfeW91bmciLCJxTlNDMV9xTlNDMiIpKSAlPiUgbXV0YXRlKGNvbXBhcmlzb24gPSBmYWN0b3IoY29tcGFyaXNvbiAsIGxldmVscyA9IGMoIm9sZF9vbGQiLCJ5b3VuZ19vbGQiLCJ5b3VuZ195b3VuZyIsInFOU0MxX3FOU0MyIikpKQp9KQpgYGAKCmBgYHtyfQpjb2xvcnNfY29tcGFyaXNvbnMgPC0gYygib2xkX29sZCIgPSAic2xhdGVibHVlIiAsInlvdW5nX29sZCIgPSAiZGVlcHNreWJsdWU0IiwgInlvdW5nX3lvdW5nIiA9ICJvbGl2ZWRyYWIiICwgInFOU0MxX3FOU0MyIiA9ICJibGFjayIpCgpnZy5saXN0IDwtIGxhcHBseSggWCA9IGRmLnBsb3QubGlzdF9yZWYsIEZVTiA9IGZ1bmN0aW9uKHgpewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdChkYXRhID0geCwgbWFwcGluZyA9IGFlcyh4ID0gZXVjbGlkZWFuX2Rpc3RhbmNlICwgY29sb3IgPSBjb21wYXJpc29uICwgZmlsbCA9IGNvbXBhcmlzb24gKSkgKyBnZW9tX2RlbnNpdHkoIGFscGhhID0gMC4zKSArIGdndGl0bGUoIHBhc3RlMCh1bmlxdWUoYXMuY2hhcmFjdGVyKHgkdHlwZSkpKSApICsgeGxhYigiRXVjbGlkZWFuIERpc3RhbmNlIikgKyB5bGFiKCJEZW5zaXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfY29tcGFyaXNvbnMpICsgc2NhbGVfY29sb3JfbWFudWFsKCB2YWx1ZXMgPSBjb2xvcnNfY29tcGFyaXNvbnMgICkgKyBsYWJzKGNvbG9yPSJDb21wYXJpc29uIixmaWxsPSJDb21wYXJpc29uIikgKyBnZ3RpdGxlKCBwYXN0ZTAodW5pcXVlKGFzLmNoYXJhY3Rlcih4JHR5cGUpKSkgKQp9KQpgYGAKCiMjIyBBc3RybwoKYGBge3IgZmlnLndpZHRoPTYsZmlnLmhlaWdodD00fQpwcmludChnZy5saXN0W1sxXV0pCmBgYAoKIyMjIGFOU0MxCgpgYGB7ciBmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTR9CnByaW50KGdnLmxpc3RbWzJdXSkKYGBgCgojIyMgYU5TQzIKCmBgYHtyIGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9NH0KcHJpbnQoZ2cubGlzdFtbM11dKQpgYGAKCiMjIyBxTlNDMQoKYGBge3IgZmlnLndpZHRoPTYsZmlnLmhlaWdodD00fQpwcmludChnZy5saXN0W1s0XV0pCmBgYAoKIyMjIHFOU0MyCgpgYGB7ciBmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTR9CnByaW50KGdnLmxpc3RbWzVdXSkKYGBgCgojIHFOU0MxIGFuZCBBc3Ryb2N5dGVzCgpgYGB7cn0KQm94UGxvdFNtYXJ0IDwtIGZ1bmN0aW9uKCB4ICwgYW5ubyAsIGlkZW50cyAsIGdlbmVzICwgdHJhbnNfbG9nMiA9IFRSVUUgLCBwdC5hbHBoYSA9IDEgLCBmYWNldF9zd2l0Y2ggPSBGQUxTRSApewogIHJlcXVpcmUoZHBseXIpCiAgcmVxdWlyZSh0aWR5cikKICByZXF1aXJlKGdncGxvdDIpCiAgcmVxdWlyZShnZ2JlZXN3YXJtKQogIHJlcXVpcmUoY293cGxvdCkKICByZXF1aXJlKGhhc2gpCgogIGVuczJnZW5lX2hhc2ggPC0gaGFzaCgga2V5cyA9IGdlbmVzICwgdmFsdWVzID0gbmFtZXMoZ2VuZXMpICkKICAKICBjZWxscyA8LSBhcy5jaGFyYWN0ZXIoIGZpbHRlciggYW5ubyAsIHR5cGUgJWluJSBpZGVudHMgKSAlPiUgcHVsbCgiY2VsbCIpICkKICAKICBkYXRhX3Zpb2xpbiA8LSBkcGx5cjo6c2VsZWN0KHggLCBvbmVfb2YoIGMoICJnZW5lX2lkIiAsIGNlbGxzICkgKSApICU+JSBmaWx0ZXIoIGdlbmVfaWQgJWluJSBnZW5lcyApCiAgCiAgZGF0YV92aW9saW5fZ2F0aGVyIDwtIGdhdGhlciggZGF0YSA9IGRhdGFfdmlvbGluICwga2V5ID0gImNlbGwiICwgdmFsdWUgPSAiVFBNIiAsIC1nZW5lX2lkICAgKQogIAogIGlmKHRyYW5zX2xvZzIpeyBkYXRhX3Zpb2xpbl9nYXRoZXIkVFBNIDwtIGxvZzIoIGRhdGFfdmlvbGluX2dhdGhlciRUUE0gKyAxICkgfQogIAogIGRhdGFfdmlvbGluX2dhdGhlcl9qb2luZWQgPC0gbGVmdF9qb2luKHggPSBkYXRhX3Zpb2xpbl9nYXRoZXIgLCB5ID0gYW5ubywgYnkgPSAiY2VsbCIpCiAgCiAgcHJpbnQoIGRhdGFfdmlvbGluX2dhdGhlcl9qb2luZWQgICU+JSBncm91cF9ieShnZW5lX2lkLHR5cGUpICU+JSBzdW1tYXJpc2UoIHBlcmNlbnQgPSBzdW0oVFBNID4gMCkvbGVuZ3RoKFRQTSkgKSAsIGdlbmVfaWQgPSBnZW5lX2lkICkKICAKICBnZW5lX2lkcyA8LSBoYXNoOjp2YWx1ZXMoZW5zMmdlbmVfaGFzaFtnZW5lc10pCgogIGdlbmVfaWRzIDwtIGdlbmVfaWRzWyEgaXMubmEoZ2VuZV9pZHMpXQoKICBnZW5lc19sYWJlbGxlcl92ZWMgPC0gZ2VuZV9pZHMKCiAgZ2VuZXNfbGFiZWxsZXIgPC0gbGFiZWxsZXIoZ2VuZV9pZCA9IGdlbmVzX2xhYmVsbGVyX3ZlYykKICAKICBkYXRhX3Zpb2xpbl9nYXRoZXJfam9pbmVkIDwtIGRwbHlyOjpmaWx0ZXIoZGF0YV92aW9saW5fZ2F0aGVyX2pvaW5lZCAsIGdlbmVfaWQgJWluJSBuYW1lcyhnZW5lc19sYWJlbGxlcl92ZWMpICkKICAKICBnIDwtIGdncGxvdChkYXRhID0gZGF0YV92aW9saW5fZ2F0aGVyX2pvaW5lZCAsIG1hcHBpbmcgPSBhZXMoeCA9IHR5cGUgLCB5ID0gVFBNICwgZmlsbCA9IHR5cGUgKSkgKyAKICAgICAgICBnZW9tX2JveHBsb3QoIG91dGxpZXIuc2hhcGUgPSBOQSApICsgICAgCiAgICAgICAgZ2VvbV9xdWFzaXJhbmRvbShhbHBoYSA9IHB0LmFscGhhICwgY29sb3IgPSAiYmxhY2siICwgc2l6ZSA9IDAuNyApICsKICAgICAgICBzY2FsZV94X2Rpc2NyZXRlKCBuYW1lID0gIklkZW50aXR5IikgKyAKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9IGlmKHRyYW5zX2xvZzIpeyJsb2cyKCBUUE0gKyAxICkifWVsc2V7IlRQTSJ9KSArIAogICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiSWRlbnRpdHkiICwgdmFsdWVzID0gYyggcU5TQzEgPSAic3RlZWxibHVlIiAsIHFOU0MyID0gInN0ZWVsYmx1ZTEiICwgQXN0cm8gPSAiZ3JleTUwIiApICkgKwogICAgICAgIGlmKCBhbGwoIGMoIm9sZCIsInlvdW5nIikgJWluJSBhcy5jaGFyYWN0ZXIoYW5ubyRhZ2UpICkgKXsKICAgICAgICAgIGlmKCEgZmFjZXRfc3dpdGNoKXsKICAgICAgICAgICAgZmFjZXRfZ3JpZChmYWNldHMgPSBnZW5lX2lkfmFnZSAsIGxhYmVsbGVyID0gZ2VuZXNfbGFiZWxsZXIpCiAgICAgICAgICB9ZWxzZXsKICAgICAgICAgICAgZmFjZXRfZ3JpZChmYWNldHMgPSBhZ2V+Z2VuZV9pZCAsIGxhYmVsbGVyID0gZ2VuZXNfbGFiZWxsZXIpICAgIAogICAgICAgICAgfSAgICAgIAogICAgICAgIH1lbHNlewogICAgICAgICAgZmFjZXRfd3JhcCggZmFjZXRzID0gImdlbmVfaWQiICwgbmNvbCA9IDEgLCBsYWJlbGxlciA9IGdlbmVzX2xhYmVsbGVyICApCiAgICAgICAgfQogICAgCiAgCiAgcmV0dXJuKGcpCn0KYGBgCgojIyBMb2FkIHRoZSBkYXRhCgpMb2FkIHRoZSBTbWFydFNlcTIgZGF0YSBmb3IgeW91bmcgYW5kIG9sZCBzZXBhcmF0ZWx5CgpgYGB7cn0Kc21hcnRzZXFfZGF0YV9vbGQgPC0gcmVhZC5jc3YoZmlsZSA9ICJjb3VudF90YWJsZS9UUE1fTlNDX2FuZF9Bc3Ryby9vbGQvR2VuZV9leHByZXNzaW9uX21hdHJpeF9UUE1fb2xkLmNzdiIgLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKQpzbWFydHNlcV9kYXRhX3lvdW5nIDwtIHJlYWQuY3N2KGZpbGUgPSAiY291bnRfdGFibGUvVFBNX05TQ19hbmRfQXN0cm8veW91bmcvR2VuZV9leHByZXNzaW9uX21hdHJpeF9UUE1feW91bmcuY3N2IiAsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IDEpCmBgYAoKSm9pbiB5b3VuZyBhbmQgb2xkCgpgYGB7cn0KIyBzbWFydHNlcV9kYXRhIDwtIGZ1bGxfam9pbih4ID0gc21hcnRzZXFfZGF0YV9vbGQgLCB5ID0gc21hcnRzZXFfZGF0YV95b3VuZykKYGBgCgoKYW5kIHRoZSBjZWxsIGFubm90YXRpb24gdG8gY2VsbHR5cGVzCgpgYGB7cn0Kc21hcnRzZXFfZGF0YV9hbm5vdGF0aW9uX29sZCA8LSByZWFkLmNzdihmaWxlID0gImNvdW50X3RhYmxlL2NlbGxfYW5ub3RhdGlvbl9OU0NfQXN0cm8vb2xkL2NlbGxfYW5ub3RhdGlvbl9vbGQuY3N2IiAsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IDEpCnNtYXJ0c2VxX2RhdGFfYW5ub3RhdGlvbl95b3VuZyA8LSByZWFkLmNzdihmaWxlID0gImNvdW50X3RhYmxlL2NlbGxfYW5ub3RhdGlvbl9OU0NfQXN0cm8veW91bmcvY2VsbF9hbm5vdGF0aW9uX3lvdW5nLmNzdiIgLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKQpgYGAKCkpvaW4geW91bmcgYW5kIG9sZAoKYGBge3J9CiMgc21hcnRzZXFfZGF0YV9hbm5vdGF0aW9uIDwtIGJpbmRfcm93cyggc21hcnRzZXFfZGF0YV9hbm5vdGF0aW9uX29sZCwgc21hcnRzZXFfZGF0YV9hbm5vdGF0aW9uX3lvdW5nICkKYGBgCgojIyBCb3hwbG90IENkOQoKYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NX0KQm94UGxvdFNtYXJ0KHggPSBzbWFydHNlcV9kYXRhX29sZCAsIGFubm8gPSBzbWFydHNlcV9kYXRhX2Fubm90YXRpb25fb2xkICwgaWRlbnRzID0gYygicU5TQzEiLCJBc3RybyIpICwgZ2VuZXMgPSBjKENkOSA9ICJFTlNNVVNHMDAwMDAwMzAzNDIiKSApCgpjZDlwbG90X29sZCA8LSBCb3hQbG90U21hcnQoeCA9IHNtYXJ0c2VxX2RhdGFfb2xkICwgYW5ubyA9IHNtYXJ0c2VxX2RhdGFfYW5ub3RhdGlvbl9vbGQgLCBpZGVudHMgPSBjKCJxTlNDMSIsIkFzdHJvIikgLCBnZW5lcyA9IGMoQ2Q5ID0gIkVOU01VU0cwMDAwMDAzMDM0MiIpICwgcHQuYWxwaGEgPSAxKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgCgpjZDlwbG90X29sZApgYGAKCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTV9CmNkOXBsb3RfeW91bmcgPC0gQm94UGxvdFNtYXJ0KHggPSBzbWFydHNlcV9kYXRhX3lvdW5nICwgYW5ubyA9IHNtYXJ0c2VxX2RhdGFfYW5ub3RhdGlvbl95b3VuZyAsIGlkZW50cyA9IGMoInFOU0MxIiwiQXN0cm8iKSAsIGdlbmVzID0gYyhDZDkgPSAiRU5TTVVTRzAwMDAwMDMwMzQyIikgLCBwdC5hbHBoYSA9IDEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAKCmNkOXBsb3RfeW91bmcKYGBgCgojIyBIZWF0bWFwIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcwoKTG9hZCB0aGUgbGlzdHMgb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGJldHdlZW4gY29ydGljYWwgQXN0cm9jeXRlcyBhbmQgcU5TQzFzLCBmb3IgY2VsbHMgZnJvbSBvbGQgbWljZS4KCmBgYHtyfQojIE9sZCAKREVnZW5lc19vbGRfdGFiIDwtIHJlYWQuY3N2KGZpbGUgPSAicmVzdWx0cy9xMV9vbGRfdnNfcTFfb2xkQXN0cm9fc2lnX3Jlc3VsdHMuY3N2IikKCkRFZ2VuZXNfb2xkX3RhYiRnZW5lX25hbWUgPC0gc3RyX3RvX3RpdGxlKERFZ2VuZXNfb2xkX3RhYiRnZW5lX25hbWUpCgplbnMyZ2VuZV9vbGQgPC0gREVnZW5lc19vbGRfdGFiIAoKREVnZW5lc19vbGRfdXAgPC0gZHBseXI6OmZpbHRlcihERWdlbmVzX29sZF90YWIgLCBsb2dfZm9sZF9jaGFuZyA+IDAgLCAhIGlzLm5hKGdlbmVfaWQpKQpERWdlbmVzX29sZF9kb3duIDwtIGRwbHlyOjpmaWx0ZXIoREVnZW5lc19vbGRfdGFiICwgbG9nX2ZvbGRfY2hhbmcgPCAwICwgISBpcy5uYShnZW5lX2lkKSkKCnNldXJhdF8xMFgyIDwtIHJlYWRSRFMoZmlsZSA9ICIuLi8xMFgvc2V1cmF0XzEwWDJfY2x1c3RlcmVkX21pbl8xNTAwX25HZW5lLlJEUyIpCgpERWdlbmVzX29sZF91cF9jb21wIDwtIGRwbHlyOjpmaWx0ZXIoREVnZW5lc19vbGRfdXAgLCBnZW5lX25hbWUgJWluJSByb3duYW1lcyhzZXVyYXRfMTBYMkBkYXRhKSApIApERWdlbmVzX29sZF9kb3duX2NvbXAgPC0gZHBseXI6OmZpbHRlcihERWdlbmVzX29sZF9kb3duICwgZ2VuZV9uYW1lICVpbiUgcm93bmFtZXMoc2V1cmF0XzEwWDJAZGF0YSkgKSAKCiMgREVnZW5lc19vbGRfdXBfY29tcCA8LSBkcGx5cjo6ZmlsdGVyKERFZ2VuZXNfb2xkX3VwICwgZ2VuZV9pZCAlaW4lIHNtYXJ0c2VxX2RhdGFfb2xkJGdlbmVfaWQgKSAKIyBERWdlbmVzX29sZF9kb3duX2NvbXAgPC0gZHBseXI6OmZpbHRlcihERWdlbmVzX29sZF9kb3duICwgZ2VuZV9pZCAlaW4lIHNtYXJ0c2VxX2RhdGFfb2xkJGdlbmVfaWQgKSAgCgojIERFZ2VuZXNfb2xkIDwtIGMoIGFzLmNoYXJhY3RlcihERWdlbmVzX29sZF91cCRnZW5lX25hbWUpICwgYXMuY2hhcmFjdGVyKERFZ2VuZXNfb2xkX2Rvd24kZ2VuZV9uYW1lKSApICAKREVnZW5lc19vbGRfZW5zIDwtIGMoIGFzLmNoYXJhY3RlcihERWdlbmVzX29sZF91cCRnZW5lX2lkKSAsIGFzLmNoYXJhY3RlcihERWdlbmVzX29sZF9kb3duJGdlbmVfaWQpICkgIAoKYW5ub19vbGQgPC0gcmVhZC5jc3YoZmlsZSA9ICJjb3VudF90YWJsZS9jZWxsX2Fubm90YXRpb25fTlNDX0FzdHJvL29sZC9jZWxsX2Fubm90YXRpb25fb2xkLmNzdiIpCgpgYGAKCiMjIyBGaWx0ZXIgdGhlIFNNQVJUc2VxMiBUUE0gdmFsdWVzIGZvciB0aGUgZ2VuZXMgdGhhdCBhcmUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkCgpgYGB7cn0KcTFjZWxscyA8LSBmaWx0ZXIoYW5ub19vbGQsIHR5cGUgPT0gInFOU0MxIikgCgpxMmNlbGxzIDwtIGZpbHRlcihhbm5vX29sZCwgdHlwZSA9PSAicU5TQzIiKSAKCmFzdHJvX2NlbGxzIDwtIGZpbHRlcihhbm5vX29sZCwgdHlwZSA9PSAiQXN0cm8iKSAKCnVwX2dlbmVfaWQgPC0gYXMuY2hhcmFjdGVyKERFZ2VuZXNfb2xkX3VwX2NvbXAkZ2VuZV9pZCkKZG93bl9nZW5lX2lkIDwtIGFzLmNoYXJhY3RlcihERWdlbmVzX29sZF9kb3duX2NvbXAkZ2VuZV9pZCkKCnVwX2dlbmVfbmFtZXMgPC0gYXMuY2hhcmFjdGVyKERFZ2VuZXNfb2xkX3VwX2NvbXAkZ2VuZV9uYW1lKSAKZG93bl9nZW5lX25hbWVzIDwtIGFzLmNoYXJhY3RlcihERWdlbmVzX29sZF9kb3duX2NvbXAkZ2VuZV9uYW1lKQoKc2NhbGVfcmVkX3doaXRlIDwtIGNvbG9yUmFtcFBhbGV0dGUoY29sb3JzID0gYygicmVkIiwid2hpdGUiKSkKYGBgCgpGZXRjaCB0aGUgZGF0YSBmcm9tIHFOU0MxLCBxTlNDMiBhbmQgQXN0cm9jeXRlcyBmb3IgdGhlIGdlbmVzCgpgYGB7cn0KZGYuaGVhdG1hcC5zbWFydF91cF9jb21wIDwtIHNtYXJ0c2VxX2RhdGFfb2xkICU+JSBkcGx5cjo6c2VsZWN0KCBvbmVfb2YoYygiZ2VuZV9pZCIsYXMuY2hhcmFjdGVyKHEyY2VsbHMkY2VsbCksYXMuY2hhcmFjdGVyKHExY2VsbHMkY2VsbCksYXMuY2hhcmFjdGVyKGFzdHJvX2NlbGxzJGNlbGwpKSkgKSAlPiUgZHBseXI6OmZpbHRlcihnZW5lX2lkICVpbiUgdXBfZ2VuZV9pZCApICU+JSBhcnJhbmdlKGdlbmVfaWQpCgpkZi5oZWF0bWFwLnNtYXJ0X2Rvd25fY29tcCA8LSBzbWFydHNlcV9kYXRhX29sZCAlPiUgZHBseXI6OnNlbGVjdCggb25lX29mKGMoImdlbmVfaWQiLGFzLmNoYXJhY3RlcihxMmNlbGxzJGNlbGwpLGFzLmNoYXJhY3RlcihxMWNlbGxzJGNlbGwpLGFzLmNoYXJhY3Rlcihhc3Ryb19jZWxscyRjZWxsKSkpICApICU+JSBkcGx5cjo6ZmlsdGVyKGdlbmVfaWQgJWluJSBkb3duX2dlbmVfaWQgKSAlPiUgYXJyYW5nZShnZW5lX2lkKQoKZGYuaGVhdG1hcC5zbWFydF9jb21wIDwtIGFzLm1hdHJpeCggYmluZF9yb3dzKCBkZi5oZWF0bWFwLnNtYXJ0X3VwX2NvbXAgLCBkZi5oZWF0bWFwLnNtYXJ0X2Rvd25fY29tcCApICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoImdlbmVfaWQiKSApCgpkZi5oZWF0bWFwLnNtYXJ0X2NvbXAgPC0gbG9nKCBhcy5tYXRyaXgoZGYuaGVhdG1hcC5zbWFydF9jb21wKSArIDEgKQpgYGAKCmBgYHtyfQphbm5vX3NtczIgPC0gYW5ub19vbGQgJT4lIGRwbHlyOjpzZWxlY3QoY2VsbCx0eXBlKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJjZWxsIikKYGBgCgojIyMgUGxvdCBIZWF0bWFwCgpgYGB7ciBmaWcuaGVpZ2h0PTE1ICwgZmlnLndpZHRoPTZ9CmhtX3NtczJfY29tcCA8LSBwaGVhdG1hcChtYXQgPSBwbWF4KCBwbWluKGRmLmhlYXRtYXAuc21hcnRfY29tcCwzKSAsIC0zICkgLCBjbHVzdGVyX3Jvd3MgPSBGQUxTRSAsIGNsdXN0ZXJfY29scyA9IEZBTFNFICwgY29sb3IgPSByZXYoc2NhbGVfcmVkX3doaXRlKDIwMCkpICAsIGJyZWFrcyA9IHNlcShmcm9tPTAsdG89MyxsZW5ndGgub3V0ID0gMjAwKSAsIG1haW4gPSAibG9nKCBUUE0gKyAxICkiICwgc2hvd19jb2xuYW1lcyA9IEZBTFNFICwgc2hvd19yb3duYW1lcyA9IEZBTFNFICwgZ2Fwc19yb3cgPSAxNzAgLCBnYXBzX2NvbCA9IGMoMTcsMTEzKSAsIGZvbnRzaXplID0gOCAsIGFubm90YXRpb25fY29sID0gYW5ub19zbXMyICwgYW5ub3RhdGlvbl9jb2xvcnMgPSBsaXN0KCB0eXBlID0gYyhxTlNDMT0ic3RlZWxibHVlIixxTlNDMj0ic3RlZWxibHVlMSIsQXN0cm89ImdyZXkiKSkgICkKYGBgCgojIFNlc3Npb25JbmZvCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgo=